This is an R Markdown Notebook for analysis using data on the DC Bus System (WMATA Metrobus). The data were obtained here:

https://planitmetro.com/2016/11/16/data-download-metrobus-vehicle-location-data/

Control + Alt + Shift + m = rename in scope

Load the packages to be used.

package ‘tidyr’ was built under R version 3.2.5package ‘plyr’ was built under R version 3.2.5package ‘stringr’ was built under R version 3.2.5package ‘geosphere’ was built under R version 3.2.5

Get the data.

First let’s check the working directory.

getwd()
[1] "/Users/mdturse/Desktop/Analytics/DCMetroBus"

Then, actually get the data.

The working directory was changed to /Users/mdturse/Desktop/Analytics/DCMetroBus/Bus AVL Oct 2016 inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the the working directory for notebook chunks.Oct03Raw
'data.frame':   620274 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 11 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : Factor w/ 10552 levels "","1000001","1000003",..: 9682 9682 9683 9641 9640 8136 9668 9668 9796 9795 ...
 $ Stop_Desc        : Factor w/ 7740 levels "10TH ST + MICHIGAN AVE",..: 1346 1346 7417 7418 1346 2940 2939 2939 6926 6929 ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : Factor w/ 75354 levels "10-3-16 1:00:00 AM",..: 47380 47506 47740 47814 47864 48244 48302 48540 49086 49190 ...
 $ Departure_Time   : Factor w/ 75396 levels "10-3-16 1:00:00 AM",..: 47406 47554 47766 47840 47890 48270 48536 48566 49112 49216 ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
Oct04Raw
'data.frame':   623427 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 225 225 225 225 225 225 225 225 225 225 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 6 6 6 6 6 6 6 ...
 $ Route_Direction  : Factor w/ 9 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 8 1 1 1 1 3 2 5 ...
 $ Stop_ID          : Factor w/ 10555 levels "","1000001","1000003",..: 9671 9671 8138 8138 8138 8138 8138 9798 9799 9638 ...
 $ Stop_Desc        : Factor w/ 7717 levels "10TH ST + MICHIGAN AVE",..: 2939 2939 2940 2940 2940 2940 2940 6906 6903 4205 ...
 $ Event_Type       : int  3 4 3 3 3 5 5 4 5 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 3 1 1 1 2 2 3 2 3 ...
 $ Event_Time       : Factor w/ 77713 levels "10-4-16 1:00:00 AM",..: 49126 49240 50858 50908 50976 51116 51172 51714 51842 51940 ...
 $ Departure_Time   : Factor w/ 77739 levels "10-4-16 1:00:00 AM",..: 49209 49251 50869 50957 50987 51165 51185 51725 51933 51951 ...
 $ Dwell_Time       : int  79 0 59 19 59 19 1 0 40 0 ...
 $ Delta_Time       : int  35 36 36 246 244 255 264 159 129 139 ...
 $ Odometer_Distance: int  56958 60750 69747 69971 69747 71136 71177 76520 77425 78353 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  58 89 82 76 79 301 274 104 310 2 ...
Oct05Raw
'data.frame':   630900 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Route_Direction  : Factor w/ 11 levels "ANTICLKW","CLOCKWIS",..: 5 5 5 5 5 5 5 5 5 5 ...
 $ Stop_Sequence    : int  1 1 3 4 5 4 3 3 7 7 ...
 $ Stop_ID          : Factor w/ 10543 levels "","1000001","1000003",..: 9659 9659 9632 9633 9624 9633 9632 9632 9673 9673 ...
 $ Stop_Desc        : Factor w/ 7725 levels "10TH ST + MICHIGAN AVE",..: 2946 2946 7403 7401 7401 7401 7403 7403 1346 1346 ...
 $ Event_Type       : int  3 5 4 4 3 4 3 3 5 5 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 2 3 3 1 3 1 1 2 2 ...
 $ Event_Time       : Factor w/ 77725 levels "10-5-16 1:00:00 AM",..: 49279 49371 49899 49953 49993 50135 50221 50493 50783 50987 ...
 $ Departure_Time   : Factor w/ 77716 levels "10-5-16 1:00:00 AM",..: 49257 49353 49877 49931 49997 50113 50421 50489 50767 50999 ...
 $ Dwell_Time       : int  189 2 0 0 13 0 111 9 3 17 ...
 $ Delta_Time       : int  4 78 -114 -3 19 93 297 191 382 499 ...
 $ Odometer_Distance: int  37932 38703 44242 44327 44645 45927 46733 47077 50461 51916 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  316 104 276 246 229 246 345 207 109 305 ...
Oct06Raw
'data.frame':   621948 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 265 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Route_Direction  : Factor w/ 9 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 7 6 5 4 3 7 7 7 ...
 $ Stop_ID          : Factor w/ 10562 levels "","1000001","1000003",..: 9678 9678 9692 9693 9643 9652 9651 9692 9692 9692 ...
 $ Stop_Desc        : Factor w/ 7723 levels "10TH ST + MICHIGAN AVE",..: 2937 2937 1342 7400 7399 7399 7401 1342 1342 1342 ...
 $ Event_Type       : int  3 5 4 5 3 4 3 4 5 5 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 2 3 2 1 3 1 3 2 2 ...
 $ Event_Time       : Factor w/ 77758 levels "10-6-16 1:00:00 AM",..: 49294 49384 49982 49998 50058 50186 50270 50518 51002 51064 ...
 $ Departure_Time   : Factor w/ 77792 levels "10-6-16 1:00:00 AM",..: 49305 49399 49993 50023 50091 50197 50487 50529 51065 51079 ...
 $ Dwell_Time       : int  148 2 0 7 11 0 103 0 26 2 ...
 $ Delta_Time       : int  -6 64 -87 -93 31 104 303 175 497 504 ...
 $ Odometer_Distance: int  37950 38726 44130 44197 44592 45935 46739 51826 51826 51838 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  284 71 199 164 223 246 343 199 306 320 ...
Oct07Raw
'data.frame':   622894 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 6 6 6 6 6 6 7 7 ...
 $ Route_Direction  : Factor w/ 7 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 2 3 3 5 6 7 1 2 ...
 $ Stop_ID          : Factor w/ 10556 levels "","1000001","1000003",..: 9672 9672 9800 9799 9799 9639 9640 9641 9641 9642 ...
 $ Stop_Desc        : Factor w/ 7699 levels "10TH ST + MICHIGAN AVE",..: 2930 2930 6886 6889 6889 4196 4199 6887 6887 4198 ...
 $ Event_Type       : int  3 4 3 4 5 4 4 3 3 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 3 1 3 2 3 3 1 1 3 ...
 $ Event_Time       : Factor w/ 77562 levels "10-7-16 1:00:00 AM",..: 49134 49136 51718 51756 51888 51934 52018 52044 52130 52288 ...
 $ Departure_Time   : Factor w/ 77649 levels "10-7-16 1:00:00 AM",..: 49193 49195 51779 51815 51953 51993 52077 52103 52189 52347 ...
 $ Dwell_Time       : int  153 0 1 0 3 0 0 120 120 0 ...
 $ Delta_Time       : int  57 56 165 270 197 201 181 189 235 288 ...
 $ Odometer_Distance: int  37846 42154 56018 56611 57411 58341 59084 59787 59787 60252 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  98 89 201 104 26 2 1 247 247 182 ...

Put the daily data together.

AllDays <- bind_rows(list(Oct03Raw, Oct04Raw, Oct05Raw, Oct06Raw, Oct07Raw),
                     .id = c("group")
                    )
Unequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to character
# dim(AllDays)
str(AllDays)
'data.frame':   3119443 obs. of  18 variables:
 $ group            : chr  "1" "1" "1" "1" ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : chr  "LOOP" "LOOP" "LOOP" "LOOP" ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : chr  "10-3-16 6:06:47 AM" "10-3-16 6:07:50 AM" "10-3-16 6:09:47 AM" "10-3-16 6:10:24 AM" ...
 $ Departure_Time   : chr  "10-3-16 6:06:47 AM" "10-3-16 6:08:01 AM" "10-3-16 6:09:47 AM" "10-3-16 6:10:24 AM" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...

Deleting old data frames.

for (i in 3:7){
  rm(list = ls(pattern = paste0("Oct0", i, "Raw")
              )
    )
  
  message("Deleting Oct0", i, "Raw")
  }
Deleting Oct03Raw
Deleting Oct04Raw
Deleting Oct05Raw
Deleting Oct06Raw
Deleting Oct07Raw

Updating variable types.

Then, sorting the data and adding a RowNumber (to be used for identifying rows later in the analyses.)

AllDays$group <- factor(AllDays$group)
AllDays$Route_Direction <- factor(AllDays$Route_Direction)
AllDays$Event_Time <- as.POSIXct(AllDays$Event_Time, format = "%m-%d-%y %I:%M:%S %p")
AllDays$Departure_Time <- as.POSIXct(AllDays$Departure_Time, format = "%m-%d-%y %I:%M:%S %p")
str(AllDays)
'data.frame':   3119443 obs. of  18 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
AllDays_Sorted <- arrange(AllDays,
                          Bus_ID,
                          Event_Time
                         ) %>% 
  mutate(RowNum_OG = row_number() # this is useful in identify the row later on
        )
rm(AllDays)
str(AllDays_Sorted)
'data.frame':   3119443 obs. of  19 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
 $ RowNum_OG        : int  1 2 3 4 5 6 7 8 9 10 ...
# View(head(AllDays_Sorted, 100))

Inspecting the values of Stop_ID, and finding that it can take the values “” (blank) and “NULL”.

View(group_by(AllDays_Sorted,
              Stop_ID
             ) %>% 
       summarise(
         Cnt = n()
         ) %>% 
       arrange(Stop_ID)
    )
View(filter(AllDays_Sorted,
            is.na(Stop_ID) |
              Stop_ID == "" |
              Stop_ID == "NULL"
           ) %>% 
       arrange(Stop_Desc)
    )

Creating a table of distinct Stop_Desc values when Stop_ID is “” (blank) or “NULL”.

StopID_New <- filter(AllDays_Sorted,
                     is.na(Stop_ID) |
                       Stop_ID == "" |
                       Stop_ID == "NULL"
                    ) %>% 
  select(Stop_ID, Stop_Desc) %>% 
  distinct() %>% 
  arrange(Stop_ID, Stop_Desc) %>% 
  mutate(StopID_New = 1:nrow(.)
        )
View(StopID_New)

Creating a full updated table by filling in StopID_New for when Stop_ID is “” (blank) or NULL.

AllDays_StopIDNew <- left_join(AllDays_Sorted,
                               select(StopID_New,
                                      Stop_Desc,
                                      StopID_New
                                     ),
                               by = c("Stop_Desc" = "Stop_Desc")
                              ) %>% 
  mutate(StopID_Clean = ifelse(is.na(StopID_New),
                               Stop_ID,
                               StopID_New
                              ),
         StopID_Indicator = factor(ifelse(is.na(StopID_New),
                                          "ID_OK",
                                          "ID_Bad"
                                         )
                                  )
        )
rm(StopID_New)
rm(AllDays_Sorted)
str(AllDays_StopIDNew)
'data.frame':   3119443 obs. of  22 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
 $ RowNum_OG        : int  1 2 3 4 5 6 7 8 9 10 ...
 $ StopID_New       : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean     : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ StopID_Indicator : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
# View(tail(AllDays_StopIDNew, 500))
# View(filter(AllDays_StopIDNew,
#             Stop_Desc == "METROWAY ANNNOUCEMNT CORR"
#            )
#     )

Feature engineering.

Inspecting incidences of consecutive Stop_IDs. This is done because investigation showed that many conseutive events occurr at the same Stop_ID, but with various Dwell_Times, Odometer_Distances, etc. All of which affect calculations and analyses.

Create data on the runs (consecutive Stop_IDs).

StopID_Runs <- rle(AllDays_StopIDNew$StopID_Clean)
StopID_Runs$ends <- cumsum(StopID_Runs$lengths)
StopID_Runs$starts <- ifelse(is.na(lag(StopID_Runs$ends)
                                  ),
                             1,
                             lag(StopID_Runs$ends) + 1
                            )
str(StopID_Runs)
List of 4
 $ lengths: int [1:2809529] 2 1 1 1 1 2 1 1 1 1 ...
 $ values : chr [1:2809529] "5004572" "5004573" "5002210" "5002209" ...
 $ ends   : int [1:2809529] 2 3 4 5 6 8 9 10 11 12 ...
 $ starts : num [1:2809529] 1 3 4 5 6 7 9 10 11 12 ...
 - attr(*, "class")= chr "rle"
# class(StopID_Runs)
# 
# StopID_Runs_df <- data.frame(unclass(StopID_Runs))
# str(StopID_Runs_df)
# class(StopID_Runs_df)
# rm(StopID_Runs_df)

Trying to link data on RunsGroups with the original data (AllDays_Sorted). The goal is to select only one record per RunsGroup - that being the record with the longest Dwell_Time.

I attempted this computation using both data.frames (dplyr) and data.tables (data.table). However, with 2,809,062 rows in one dataset and 3,119,443 rows in the other dataset, the current computation time is over 5 days…so I’m trying a different strategy to only select the first record in a run.

# Create a RunsGroup variable for each run
# StopID_Runs_df$RunsGroup <- paste0("g", seq(1:nrow(StopID_Runs_df)
#                                            )
#                                   )
# 
# str(StopID_Runs_df)
# head(StopID_Runs_df, 25)
# tail(StopID_Runs_df, 25)
# 
# StopID_Runs_df <- StopID_Runs_df %>% 
#   mutate(RowNum = row_number()
#         )
# 
# str(StopID_Runs_df)
# head(StopID_Runs_df, 25)
# tail(StopID_Runs_df, 25)
# 
# 
# # Converting to data.tables for, hopefully, improved performance (speed) in computation
# StopID_Runs_dt <- data.table(StopID_Runs_df)
# setkey(StopID_Runs_dt, RowNum)
# str(StopID_Runs_dt)
# 
# AllDays_Sorted_dt <- data.table(AllDays_Sorted)
# setkey(AllDays_Sorted_dt, RowNum_OG)
# str(AllDays_Sorted_dt)
# # rm(AllDays_Sorted_dt)
# 
# 
# # Actual loop to perform the computations and link to original data (AllDays_Sorted_dt)
# GroupData <- list()
# for(i in 1:nrow(StopID_Runs_dt)
#    ) {
#   assign(paste0("group_", i),
#            StopID_Runs_dt[RowNum == i, RunsGroup]
#           )
# 
#     #####  The code below is the same code as above, but done with dplyr  #####
# 
#     # assign(paste0("group_", i),
#   #        filter(StopID_Runs_df,
#   #               RowNum == i
#   #              ) %>% 
#   #          select(RunsGroup)
#   #       )
# 
#   assign(paste0("group_", i, "_start"),
#          StopID_Runs_dt[RowNum == i, starts]
#         )
# 
#   assign(paste0("group_", i, "_end"),
#          StopID_Runs_dt[RowNum == i, ends]
#         )
# 
#   assign(paste0("group_", i, "_rows"),
#          AllDays_Sorted_dt[RowNum_OG >= as.numeric(get(paste0("group_", i, "_start")
#                                                       )
#                                                   ) &
#                            RowNum_OG <= as.numeric(get(paste0("group_", i, "_end")
#                                                       )
#                                                   ),
#                            RunsGroup := as.character(get(paste0("group_", i)
#                                                         )
#                                                     )
#                           ]
# 
#     #####  The code below is the same as the code above, but done with dplyr  #####
# 
#          # filter(AllDays_Sorted,
#          #        between(RowNum_OG,
#          #                as.numeric(get(paste0("group_", i, "_start")
#          #                              )
#          #                          ),
#          #                as.numeric(get(paste0("group_", i, "_end")
#          #                              )
#          #                          )
#          #               )
#          #       ) %>% 
#          #   mutate(RunsGroup = as.character(get(paste0("group_", i)
#          #                                     )
#          #                                 )
#          #        )
#         )
# 
#   GroupData[[i]] <- get(paste0("group_", i, "_rows"))
# 
#   message("Processing Group ", i, " of 2,809,062")
# }
# 
# 
# GroupData_df <- rbind.fill(GroupData)
# str(GroupData_df)
# head(GroupData_df)
# tail(GroupData_df)
# # rm(GroupData_df)
# 
# 
# group_1
# group_1_start
# group_1_end
# group_1_rows
# group_2_rows
# group_3_rows
# group_50_rows
# str(group_50_rows)
# group_2809062_rows
# GroupData[[1]]
# GroupData[[50]]
# 
# 
# #####  Testing Area (Below)  #####
# #####  Testing Area (Below)  #####
# #####  Testing Area (Below)  #####
# 
# # head(StopID_Runs$starts, 20)
# # head(AllDays_NewOrder$Stop_ID, 20)
# # 
# # 
# # dat <- as.data.frame(c(1,1,7,7,7,9,6,8,2,2,2,1,1,1,1,1))
# # colnames(dat)[1] <- "dat"
# # r <- rle(dat$dat)
# # dat$run <- rep(r$lengths, r$lengths)
# # dat$runLag <- lag(dat$run)
# # dat$cond <- rep(r$values, r$lengths)
# # dat
# # View(dat)

When consecutive Stop_ID occurrs, only take the first occurrence. This is done because the computation time to select only the record with the longest Dwell_Time for each run was too long (over 5 days).

This is probably less than ideal with regards to Dwell_Time, but should not make much difference for calculations of travel time, speed, etc.

AllDays_FirstStopID <- AllDays_StopIDNew[StopID_Runs$starts, ]
dim(AllDays_StopIDNew)
[1] 3119443      22
dim(AllDays_FirstStopID)
[1] 2809529      22
nrow(AllDays_StopIDNew) - nrow(AllDays_FirstStopID)
[1] 309914
rm(AllDays_StopIDNew)
rm(StopID_Runs)
str(AllDays_FirstStopID)
'data.frame':   2809529 obs. of  22 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type       : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time       : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time       : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance: int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG        : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New       : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean     : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...

Feature engineering.

Creating new variables.

AllDays_AddVars <- mutate(AllDays_FirstStopID,
                          Odometer_Distance_Mi = Odometer_Distance / 5280, #5,280 feet in 1 mile
                          Dwell_Time2 = as.numeric(Departure_Time - Event_Time),
                          Event_Time_Yr = as.integer(year(Event_Time)),
                          Event_Time_Mth = as.integer(month(Event_Time)),
                          Event_Time_Date = day(Event_Time),
                          Event_Time_Day = wday(Event_Time, label = TRUE),
                          Event_Time_Hr = hour(Event_Time),
                          Event_Time_Min = minute(Event_Time),
                          Event_Time_HrGroup = factor(ifelse(Event_Time_Hr < 3,
                                                             "Group0_2",
                                                      ifelse(Event_Time_Hr < 6,
                                                             "Group3_5",
                                                      ifelse(Event_Time_Hr < 9,
                                                             "Group6_8",
                                                      ifelse(Event_Time_Hr < 12,
                                                             "Group9_11",
                                                      ifelse(Event_Time_Hr < 15,
                                                             "Group12_14",
                                                      ifelse(Event_Time_Hr < 18,
                                                             "Group15_17",
                                                      ifelse(Event_Time_Hr < 21,
                                                             "Group18_20",
                                                      ifelse(Event_Time_Hr < 24,
                                                             "Group21_23"
                                                            )))))))),
                                                         levels = c("Group0_2",
                                                                    "Group3_5",
                                                                    "Group6_8",
                                                                    "Group9_11",
                                                                    "Group12_14",
                                                                    "Group15_17",
                                                                    "Group18_20",
                                                                    "Group21_23"
                                                                   ),
                                                         ordered = TRUE
                                                     )
                         )
rm(AllDays_FirstStopID)
str(AllDays_AddVars)
'data.frame':   2809529 obs. of  31 variables:
 $ group               : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID              : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route               : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt            : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction     : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence       : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID             : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc           : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type          : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description   : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time          : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time      : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time          : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time          : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance   : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude            : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude           : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading             : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG           : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New          : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean        : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator    : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi: num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2         : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr       : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth      : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date     : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day      : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr       : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min      : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup  : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
# group_by(AllDays_AddVars,
#          Event_Time_HrGroup
#         ) %>% 
#   summarise(Cnts = n()
#            )
# View(head(filter(AllDays_AddVars,
#                  Event_Time_Hr == 0
#                 ),
#           50
#          )
#     )
# View(head(AllDays_AddVars, 50))

Feature engineering.

Creating more variables. Creating a BusEvent row number for future identification purposes. Then, creating various variables to analyze distance traveled and speed.

AllDays_BusDay <- group_by(AllDays_AddVars,
                           Bus_ID,
                           Event_Time_Date
                          ) %>% 
  mutate(BusDay_EventNum = row_number(),  # used to identify Bus movements on a particular date
         
         Odometer_Distance_Lag1 = lag(Odometer_Distance),
         
         Latitude_L1 = lag(Latitude),
         Longitude_L1 = lag(Longitude),
         # Lat_Radian = Latitude*pi/180,
         # Long_Radian = Longitude*pi/180,
         # Lat_Radian_L1 = lag(Lat_Radian),
         # Long_Radian_L1 = lag(Long_Radian),
         
         # accounting for potential negative distances
         TravelDistance_Ft = ifelse(Odometer_Distance > Odometer_Distance_Lag1,
                                    Odometer_Distance - Odometer_Distance_Lag1,
                                    NA
                                   ),
         TravelDistance_Mi = TravelDistance_Ft / 5280, #5,280 feet in 1 mile
         
         # TravelDistance_Mi2 = gcd.hf(long1 = Long_Radian_L1,
         #                             lat1 = Lat_Radian_L1,
         #                             long2 = Long_Radian,
         #                             lat2 = Lat_Radian
         #                            ),
         
         TravelDistance_Mi_Hvrs = 
                              # ifelse((is.na(Longitude_L1) | is.na(Latitude_L1)
                              #        ),
                              #        NA,
                              distHaversine(cbind(Longitude_L1, Latitude_L1),
                                            cbind(Longitude, Latitude)
                                           ) * 0.000621371, # 0.000621371 miles = 1 meter
         
         # accounting for potential negative times
         TravelTime_Sec = as.numeric(ifelse(Event_Time > lag(Departure_Time),
                                            Event_Time - lag(Departure_Time),
                                            NA
                                           )
                                    ),
         TravelTime_Hr = TravelTime_Sec / 3600, # 3,600 seconds in 1 hour
         
         # accounting for potential negative or zero travel times
         SpeedAvg_Mph = ifelse(TravelTime_Hr > 0,
                               TravelDistance_Mi / TravelTime_Hr,
                               NA
                              ),
         
         Start_ID = lag(StopID_Clean),
         Start_Desc = lag(Stop_Desc),
         StartStop_ID = ifelse(is.na(Start_ID),
                               paste("NULL", StopID_Clean, sep = "--"),
                               paste(Start_ID, StopID_Clean, sep = "--")
                              )
        ) %>% 
  as.data.frame()
rm(AllDays_AddVars)
str(AllDays_BusDay)
'data.frame':   2809529 obs. of  44 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
# summary(AllDays_BusDay)
# View(tail(AllDays_BusDay, 50))

Inspecting for issues with StartStop_ID (where the value is either NA or contains NULL). They ONLY exist when BusDay_EventNum = 1 (which is by design). So everything looks OK.

View(group_by(AllDays_BusDay,
              StartStop_ID
             ) %>% 
       summarise(
         Cnt = n()
       ) %>% 
       arrange(desc(Cnt)
              )
    )
View(filter(AllDays_BusDay,
            (is.na(StartStop_ID) |
              str_detect(StartStop_ID, "NULL")
            ) &
              BusDay_EventNum != 1
           )
    )

Stats (quantiles) overall for TravelDistance_Mi.

Quantiles_dt <- AllDays_BusDay %>% 
  mutate(TD_Mi_q2 = quantile(x = TravelDistance_Mi, probs = 0.02, na.rm = TRUE),
         TD_Mi_q98 = quantile(x = TravelDistance_Mi, probs = 0.98, na.rm = TRUE),
         TT_Sec_q2 = quantile(x = TravelTime_Sec, probs = 0.02, na.rm = TRUE),
         TT_Sec_q98 = quantile(x = TravelTime_Sec, probs = 0.98, na.rm = TRUE),
         TT_Hr_q2 = quantile(x = TravelTime_Hr, probs = 0.02, na.rm = TRUE),
         TT_Hr_q98 = quantile(x = TravelTime_Hr, probs = 0.98, na.rm = TRUE)
        ) %>% 
  data.table()
Stats <- Quantiles_dt %>% 
  mutate(TD_Mi_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_Mean_F = mean(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98],
                             na.rm = TRUE
                            ),
         TD_Mi_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_Med_F = median(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98],
                              na.rm = TRUE
                             ),
         TD_Mi_Cnt = sum(!is.na(TravelDistance_Mi)
                        ),
         TD_Mi_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98]
                                 )
                          ),
            
         TT_Sec_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_Mean_F = mean(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98],
                              na.rm = TRUE
                             ),
         TT_Sec_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_Med_F = median(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98],
                               na.rm = TRUE
                              ),
         TT_Sec_Cnt = sum(!is.na(TravelTime_Sec)
                         ),
         TT_Sec_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98]
                                   )
                           ),
         TT_Hr_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_Mean_F = mean(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98],
                             na.rm = TRUE
                            ),
         TT_Hr_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_Med_F = median(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98],
                              na.rm = TRUE
                             ),
         TT_Hr_Cnt = sum(!is.na(TravelTime_Hr)
                        ),
         TT_Hr_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98]
                                 )
                          )
        ) %>% 
  data.frame()
rm(AllDays_BusDay)
rm(Quantiles_dt)
str(Stats)
'data.frame':   2809529 obs. of  68 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
# View(head(Stats, 50))

Stats for StartStop_ID.

Quantiles_SS_dt <- group_by(Stats,
                            StartStop_ID
                           ) %>% 
  mutate(TD_Mi_SS_q5 = quantile(x = TravelDistance_Mi, probs = 0.05, na.rm = TRUE),
         TD_Mi_SS_q95 = quantile(x = TravelDistance_Mi, probs = 0.95, na.rm = TRUE),
         TT_Sec_SS_q5 = quantile(x = TravelTime_Sec, probs = 0.05, na.rm = TRUE),
         TT_Sec_SS_q95 = quantile(x = TravelTime_Sec, probs = 0.95, na.rm = TRUE),
         TT_Hr_SS_q5 = quantile(x = TravelTime_Hr, probs = 0.05, na.rm = TRUE),
         TT_Hr_SS_q95 = quantile(x = TravelTime_Hr, probs = 0.95, na.rm = TRUE)
        ) %>% 
  data.table()
Stats_StSt <- group_by(Quantiles_SS_dt,
                       StartStop_ID
                      ) %>% 
  mutate(TD_Mi_SS_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SS_Mean_F = mean(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95],
                                na.rm = TRUE
                               ),
         TD_Mi_SS_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SS_Med_F = median(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95],
                                 na.rm = TRUE
                                ),
         TD_Mi_SS_Cnt = sum(!is.na(TravelDistance_Mi)
                           ),
         TD_Mi_SS_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95]
                                    )
                             ),
            
         TT_Sec_SS_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SS_Mean_F = mean(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95],
                                 na.rm = TRUE
                                ),
         TT_Sec_SS_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SS_Med_F = median(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95],
                                  na.rm = TRUE
                                 ),
         TT_Sec_SS_Cnt = sum(!is.na(TravelTime_Sec)),
         TT_Sec_SS_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95]
                                     )
                              ),
         TT_Hr_SS_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SS_Mean_F = mean(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95],
                                na.rm = TRUE
                               ),
         TT_Hr_SS_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SS_Med_F = median(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95],
                                 na.rm = TRUE
                                ),
         TT_Hr_SS_Cnt = sum(!is.na(TravelTime_Hr)),
         TT_Hr_SS_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95]
                                    )
                             )
        ) %>% 
  data.frame()
rm(Stats)
rm(Quantiles_SS_dt)
str(Stats_StSt)
'data.frame':   2809529 obs. of  92 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SS_Med          : num  NA 0.0621 0.0103 0.0182 0.0503 ...
 $ TT_Hr_SS_Med_F        : num  NA 0.0621 0.0103 0.0182 NA ...
 $ TT_Hr_SS_Cnt          : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Hr_SS_Cnt_F        : int  0 12 1 2 0 156 18 127 128 9 ...
# View(head(Stats_StSt, 50))

Stats for StartStop_ID with Event_Time_HrGroup.

Quantiles_SSHG_dt <- group_by(Stats_StSt,
                              StartStop_ID,
                              Event_Time_HrGroup
                             ) %>% 
  mutate(TD_Mi_SSHG_q5 = quantile(x = TravelDistance_Mi, probs = 0.05, na.rm = TRUE),
         TD_Mi_SSHG_q95 = quantile(x = TravelDistance_Mi, probs = 0.95, na.rm = TRUE),
         TT_Sec_SSHG_q5 = quantile(x = TravelTime_Sec, probs = 0.05, na.rm = TRUE),
         TT_Sec_SSHG_q95 = quantile(x = TravelTime_Sec, probs = 0.95, na.rm = TRUE),
         TT_Hr_SSHG_q5 = quantile(x = TravelTime_Hr, probs = 0.05, na.rm = TRUE),
         TT_Hr_SSHG_q95 = quantile(x = TravelTime_Hr, probs = 0.95, na.rm = TRUE)
        ) %>% 
  data.table()
Stats_StSt_HrGrp <- group_by(Quantiles_SSHG_dt,
                             StartStop_ID,
                             Event_Time_HrGroup
                            ) %>% 
  mutate(TD_Mi_SSHG_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SSHG_Mean_F = mean(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95],
                                  na.rm = TRUE
                                 ),
         TD_Mi_SSHG_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SSHG_Med_F = median(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TD_Mi_SSHG_Cnt = sum(!is.na(TravelDistance_Mi)
                             ),
         TD_Mi_SSHG_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95]
                                      )
                               ),
            
         TT_Sec_SSHG_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SSHG_Mean_F = mean(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TT_Sec_SSHG_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SSHG_Med_F = median(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95],
                                    na.rm = TRUE
                                   ),
         TT_Sec_SSHG_Cnt = sum(!is.na(TravelTime_Sec)),
         TT_Sec_SSHG_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95]
                                       )
                                ),
         TT_Hr_SSHG_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SSHG_Mean_F = mean(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95],
                                  na.rm = TRUE
                                 ),
         TT_Hr_SSHG_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SSHG_Med_F = median(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TT_Hr_SSHG_Cnt = sum(!is.na(TravelTime_Hr)),
         TT_Hr_SSHG_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95]
                                      )
                               )
        ) %>% 
  data.frame()
rm(Stats_StSt)
rm(Quantiles_SSHG_dt)
str(Stats_StSt_HrGrp)
'data.frame':   2809529 obs. of  116 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SS_Med          : num  NA 0.0621 0.0103 0.0182 0.0503 ...
 $ TT_Hr_SS_Med_F        : num  NA 0.0621 0.0103 0.0182 NA ...
 $ TT_Hr_SS_Cnt          : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Hr_SS_Cnt_F        : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TD_Mi_SSHG_q5         : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95        : num  NA 0.627 0.242 0.7 0.182 ...
 $ TT_Sec_SSHG_q5        : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95       : num  NA 276 37 25 190 ...
 $ TT_Hr_SSHG_q5         : num  NA 0.01656 0.01028 0.00694 0.05278 ...
 $ TT_Hr_SSHG_q95        : num  NA 0.07653 0.01028 0.00694 0.05278 ...
 $ TD_Mi_SSHG_Mean       : num  NaN 0.442 0.242 0.7 0.182 ...
  [list output truncated]
# View(head(Stats_StSt_HrGrp, 50))

Feature engineering.

Creating a BusEventRoute row number, and a RouteAlt_Lag1 indicator for future identification purposes.

# rm(Quantiles_dt)
# rm(Quantiles_SS_dt)
# rm(AllDays_BusDay)
# rm(Quantiles_SSHG_dt)
# rm(Stats_StSt)
AllDays_BusDayRoute <- group_by(Stats_StSt_HrGrp,
                                Bus_ID,
                                Event_Time_Date,
                                Route
                               ) %>% 
  mutate(RouteAlt_Lag1 = lag(RouteAlt)  # used in future analyses to identify Route changes
         # Odometer_Distance_Lag1 = lag(Odometer_Distance),
         # 
         # # accounting for potential negative distances
         # TravelDistance_Ft = ifelse(Odometer_Distance >= Odometer_Distance_Lag1,
         #                            Odometer_Distance - Odometer_Distance_Lag1,
         #                            NA
         #                           ),
         # TravelDistance_Mi = TravelDistance_Ft / 5280, #5,280 feet in 1 mile
         # 
         # # accounting for potential negative times
         # TravelTime_Sec = as.numeric(ifelse(Event_Time >= lag(Departure_Time),
         #                                    Event_Time - lag(Departure_Time),
         #                                    NA
         #                                   )
         #                            ),
         # TravelTime_Hr = TravelTime_Sec / 3600, # 3,600 seconds in 1 hour
         # 
         # # accounting for potential negative or zero travel times
         # SpeedAvg_Mph = ifelse(TravelTime_Hr > 0,
         #                       TravelDistance_Mi / TravelTime_Hr,
         #                       NA
         #                      )
        ) %>% 
  data.frame()
rm(Stats_StSt_HrGrp)
str(AllDays_BusDayRoute)
'data.frame':   2809529 obs. of  117 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SS_Med          : num  NA 0.0621 0.0103 0.0182 0.0503 ...
 $ TT_Hr_SS_Med_F        : num  NA 0.0621 0.0103 0.0182 NA ...
 $ TT_Hr_SS_Cnt          : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Hr_SS_Cnt_F        : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TD_Mi_SSHG_q5         : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95        : num  NA 0.627 0.242 0.7 0.182 ...
 $ TT_Sec_SSHG_q5        : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95       : num  NA 276 37 25 190 ...
 $ TT_Hr_SSHG_q5         : num  NA 0.01656 0.01028 0.00694 0.05278 ...
 $ TT_Hr_SSHG_q95        : num  NA 0.07653 0.01028 0.00694 0.05278 ...
 $ TD_Mi_SSHG_Mean       : num  NaN 0.442 0.242 0.7 0.182 ...
  [list output truncated]

Feature engineering.

Calculating a variable to know if the RouteAlt changed. Could be useful in helping identifying weirdness in calculated distances and speeds.

# rm(Stats_StSt_HrGrp)
AllDays_DirChange <- AllDays_BusDayRoute %>% 
  mutate(DirChange = ifelse(RouteAlt == RouteAlt_Lag1,
                            "Same",
                            "Change"
                           ),
         DirChange2 = factor(ifelse(is.na(DirChange),
                                    "Change",
                                    DirChange
                                   )
                            )
        )
rm(AllDays_BusDayRoute)
str(AllDays_DirChange)
'data.frame':   2809529 obs. of  119 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SS_Med          : num  NA 0.0621 0.0103 0.0182 0.0503 ...
 $ TT_Hr_SS_Med_F        : num  NA 0.0621 0.0103 0.0182 NA ...
 $ TT_Hr_SS_Cnt          : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Hr_SS_Cnt_F        : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TD_Mi_SSHG_q5         : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95        : num  NA 0.627 0.242 0.7 0.182 ...
 $ TT_Sec_SSHG_q5        : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95       : num  NA 276 37 25 190 ...
 $ TT_Hr_SSHG_q5         : num  NA 0.01656 0.01028 0.00694 0.05278 ...
 $ TT_Hr_SSHG_q95        : num  NA 0.07653 0.01028 0.00694 0.05278 ...
 $ TD_Mi_SSHG_Mean       : num  NaN 0.442 0.242 0.7 0.182 ...
  [list output truncated]

Re-ordering the variables to ease with comprehension.

AllDays_NewOrder <-  select(AllDays_DirChange,
                            RowNum_OG,
                            group,
                            StartStop_ID,
                            BusDay_EventNum,
                            Bus_ID,
                            Route,
                            RouteAlt,
                            # RouteAlt_Lag1,
                            DirChange2,
                            Route_Direction,
                            Stop_Sequence,
                            Start_ID,
                            Start_Desc,
                            # Stop_ID,
                            StopID_Clean,
                            StopID_Indicator,
                            Stop_Desc,
                            Event_Type,
                            Event_Description,
                            Event_Time_Yr,
                            Event_Time_Mth,
                            Event_Time_Date,
                            Event_Time_Day,
                            Event_Time_Hr,
                            Event_Time_HrGroup,
                            Event_Time_Min,
                            Event_Time,
                            Departure_Time,
                            Dwell_Time,
                            Dwell_Time2,
                            Delta_Time,
                            Latitude,
                            Longitude,
                            Heading,
                            Odometer_Distance,
                            Odometer_Distance_Lag1,
                            Odometer_Distance_Mi,
                            TravelDistance_Ft,
                            TravelDistance_Mi,
                            TravelDistance_Mi_Hvrs,
                            TD_Mi_q2,
                            TD_Mi_q98,
                            TD_Mi_SS_q5,
                            TD_Mi_SS_q95,
                            TD_Mi_SSHG_q5,
                            TD_Mi_SSHG_q95,
                            TD_Mi_Mean,
                            TD_Mi_Mean_F,
                            TD_Mi_SS_Mean,
                            TD_Mi_SS_Mean_F,
                            TD_Mi_SSHG_Mean,
                            TD_Mi_SSHG_Mean_F,
                            TD_Mi_Med,
                            TD_Mi_Med_F,
                            TD_Mi_SS_Med,
                            TD_Mi_SS_Med_F,
                            TD_Mi_SSHG_Med,
                            TD_Mi_SSHG_Med_F,
                            TD_Mi_Cnt,
                            TD_Mi_Cnt_F,
                            TD_Mi_SS_Cnt,
                            TD_Mi_SS_Cnt_F,
                            TD_Mi_SSHG_Cnt,
                            TD_Mi_SSHG_Cnt_F,
                            TravelTime_Sec,
                            TT_Sec_q2,
                            TT_Sec_q98,
                            TT_Sec_SS_q5,
                            TT_Sec_SS_q95,
                            TT_Sec_SSHG_q5,
                            TT_Sec_SSHG_q95,
                            TT_Sec_Mean,
                            TT_Sec_Mean_F,
                            TT_Sec_SS_Mean,
                            TT_Sec_SS_Mean_F,
                            TT_Sec_SSHG_Mean,
                            TT_Sec_SSHG_Mean_F,
                            TT_Sec_Med,
                            TT_Sec_Med_F,
                            TT_Sec_SS_Med,
                            TT_Sec_SS_Med_F,
                            TT_Sec_SSHG_Med,
                            TT_Sec_SSHG_Med_F,
                            TT_Sec_Cnt,
                            TT_Sec_Cnt_F,
                            TT_Sec_SS_Cnt,
                            TT_Sec_SS_Cnt_F,
                            TT_Sec_SSHG_Cnt,
                            TT_Sec_SSHG_Cnt_F,
                            TravelTime_Hr,
                            TT_Hr_q2,
                            TT_Hr_q98,
                            TT_Hr_SS_q5,
                            TT_Hr_SS_q95,
                            TT_Hr_SSHG_q5,
                            TT_Hr_SSHG_q95,
                            TT_Hr_Mean,
                            TT_Hr_Mean_F,
                            TT_Hr_SS_Mean,
                            TT_Hr_SS_Mean_F,
                            TT_Hr_SSHG_Mean,
                            TT_Hr_SSHG_Mean_F,
                            TT_Hr_Med,
                            TT_Hr_Med_F,
                            TT_Hr_SS_Med,
                            TT_Hr_SS_Med_F,
                            TT_Hr_SSHG_Med,
                            TT_Hr_SSHG_Med_F,
                            TT_Hr_Cnt,
                            TT_Hr_Cnt_F,
                            TT_Hr_SS_Cnt,
                            TT_Hr_SS_Cnt_F,
                            TT_Hr_SSHG_Cnt,
                            TT_Hr_SSHG_Cnt_F,
                            SpeedAvg_Mph
                           )
rm(AllDays_DirChange)
str(AllDays_NewOrder)
'data.frame':   2809529 obs. of  113 variables:
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ DirChange2            : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 1 2 2 2 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TD_Mi_SSHG_q5         : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95        : num  NA 0.627 0.242 0.7 0.182 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SSHG_Mean       : num  NaN 0.442 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Mean_F     : num  NaN 0.491 0.242 0.7 0.182 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SSHG_Med        : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Med_F      : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TD_Mi_SSHG_Cnt        : int  0 7 1 1 1 23 6 29 28 3 ...
 $ TD_Mi_SSHG_Cnt_F      : int  0 5 1 1 1 19 4 25 24 1 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Sec_SSHG_q5        : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95       : num  NA 276 37 25 190 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SSHG_Mean      : num  NaN 202 37 25 190 ...
 $ TT_Sec_SSHG_Mean_F    : num  NaN 226 37 25 190 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SSHG_Med       : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_SSHG_Med_F     : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Sec_SSHG_Cnt       : int  0 7 1 1 1 35 6 36 35 3 ...
 $ TT_Sec_SSHG_Cnt_F     : int  0 5 1 1 1 31 4 32 32 1 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TT_Hr_SSHG_q5         : num  NA 0.01656 0.01028 0.00694 0.05278 ...
 $ TT_Hr_SSHG_q95        : num  NA 0.07653 0.01028 0.00694 0.05278 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SSHG_Mean       : num  NaN 0.05615 0.01028 0.00694 0.05278 ...
  [list output truncated]
# View(head(AllDays_NewOrder, 500))
# View(tail(AllDays_NewOrder, 500))

Summarizing the data to help spot anomolies.

summary(AllDays_NewOrder)
   RowNum_OG       group      StartStop_ID       BusDay_EventNum      Bus_ID    
 Min.   :      1   1:559521   Length:2809529     Min.   :   1.0   Min.   :  11  
 1st Qu.: 784722   2:561389   Class :character   1st Qu.: 113.0   1st Qu.:2922  
 Median :1563300   3:567794   Mode  :character   Median : 248.0   Median :6195  
 Mean   :1562504   4:559180                      Mean   : 290.5   Mean   :5382  
 3rd Qu.:2337981   5:561645                      3rd Qu.: 428.0   3rd Qu.:7104  
 Max.   :3119443                                 Max.   :1344.0   Max.   :8105  
                                                                                
    Route              RouteAlt        DirChange2      Route_Direction  
 Length:2809529     2      :1128810   Change:  67071   SOUTH   :739235  
 Class :character   1      :1065425   Same  :2742458   NORTH   :735203  
 Mode  :character   3      : 260372                    WEST    :649706  
                    4      : 130801                    EAST    :628074  
                    5      :  75039                    LOOP    : 35611  
                    6      :  56408                    CLOCKWIS: 10671  
                    (Other):  92674                    (Other) : 11029  
 Stop_Sequence      Start_ID          Start_Desc        StopID_Clean      
 Min.   :  1.00   Length:2809529     Length:2809529     Length:2809529    
 1st Qu.: 12.00   Class :character   Class :character   Class :character  
 Median : 24.00   Mode  :character   Mode  :character   Mode  :character  
 Mean   : 26.83                                                           
 3rd Qu.: 39.00                                                           
 Max.   :104.00                                                           
                                                                          
 StopID_Indicator  Stop_Desc           Event_Type 
 ID_Bad:  18948   Length:2809529     Min.   :3.0  
 ID_OK :2790581   Class :character   1st Qu.:3.0  
                  Mode  :character   Median :4.0  
                                     Mean   :3.6  
                                     3rd Qu.:4.0  
                                     Max.   :5.0  
                                                  
                                          Event_Description   Event_Time_Yr 
 Serviced Stop                                     :1127366   Min.   :2016  
 Unknown Stop                                      :   2579   1st Qu.:2016  
 UnServiced Stop                                   :1679584   Median :2016  
                                                              Mean   :2016  
                                                              3rd Qu.:2016  
                                                              Max.   :2016  
                                                                            
 Event_Time_Mth Event_Time_Date Event_Time_Day Event_Time_Hr    Event_Time_HrGroup
 Min.   :10     Min.   :3.000   Sun  :     0   Min.   : 0.00   Group6_8  :611612  
 1st Qu.:10     1st Qu.:4.000   Mon  :559521   1st Qu.: 8.00   Group15_17:560103  
 Median :10     Median :5.000   Tues :561389   Median :13.00   Group18_20:461056  
 Mean   :10     Mean   :5.001   Wed  :567794   Mean   :12.97   Group9_11 :396514  
 3rd Qu.:10     3rd Qu.:6.000   Thurs:559180   3rd Qu.:18.00   Group12_14:353603  
 Max.   :10     Max.   :7.000   Fri  :561645   Max.   :23.00   Group21_23:244522  
                                Sat  :     0                   (Other)   :182119  
 Event_Time_Min    Event_Time                  Departure_Time               
 Min.   : 0.00   Min.   :2016-10-03 00:00:00   Min.   :2016-10-03 00:00:00  
 1st Qu.:14.00   1st Qu.:2016-10-04 08:36:14   1st Qu.:2016-10-04 08:36:20  
 Median :29.00   Median :2016-10-05 13:49:29   Median :2016-10-05 13:49:38  
 Mean   :29.43   Mean   :2016-10-05 13:29:21   Mean   :2016-10-05 13:29:28  
 3rd Qu.:44.00   3rd Qu.:2016-10-06 17:58:06   3rd Qu.:2016-10-06 17:58:13  
 Max.   :59.00   Max.   :2016-10-07 23:59:59   Max.   :2016-10-08 00:12:31  
                                                                            
   Dwell_Time       Dwell_Time2         Delta_Time         Latitude    
 Min.   :   0.00   Min.   :   0.000   Min.   :-5606.0   Min.   : 0.00  
 1st Qu.:   0.00   1st Qu.:   0.000   1st Qu.:   14.0   1st Qu.:38.86  
 Median :   0.00   Median :   0.000   Median :  157.0   Median :38.90  
 Mean   :  12.56   Mean   :   6.359   Mean   :  268.8   Mean   :38.91  
 3rd Qu.:   5.00   3rd Qu.:   4.000   3rd Qu.:  396.0   3rd Qu.:38.96  
 Max.   :6205.00   Max.   :6205.000   Max.   : 9426.0   Max.   :39.19  
                                                                       
   Longitude         Heading      Odometer_Distance  Odometer_Distance_Lag1
 Min.   :-77.45   Min.   :  0.0   Min.   :       0   Min.   :       0      
 1st Qu.:-77.07   1st Qu.: 89.0   1st Qu.:  177595   1st Qu.:  177326      
 Median :-77.02   Median :180.0   Median :  377510   Median :  376934      
 Mean   :-77.02   Mean   :176.9   Mean   :  426254   Mean   :  425713      
 3rd Qu.:-76.97   3rd Qu.:269.0   3rd Qu.:  623667   3rd Qu.:  622879      
 Max.   :  0.00   Max.   :360.0   Max.   :11108034   Max.   :10853226      
                                                     NA's   :6528          
 Odometer_Distance_Mi TravelDistance_Ft TravelDistance_Mi TravelDistance_Mi_Hvrs
 Min.   :   0.00      Min.   :      1   Min.   :  0.0     Min.   : 0.000        
 1st Qu.:  33.64      1st Qu.:    699   1st Qu.:  0.1     1st Qu.: 0.106        
 Median :  71.50      Median :   1044   Median :  0.2     Median : 0.142        
 Mean   :  80.73      Mean   :   1624   Mean   :  0.3     Mean   : 0.201        
 3rd Qu.: 118.12      3rd Qu.:   1518   3rd Qu.:  0.3     3rd Qu.: 0.193        
 Max.   :2103.79      Max.   :1323464   Max.   :250.7     Max.   :24.407        
                      NA's   :322734    NA's   :322734    NA's   :6528          
    TD_Mi_q2         TD_Mi_q98       TD_Mi_SS_q5       TD_Mi_SS_q95    
 Min.   :0.05208   Min.   :0.9585   Min.   :  0.000   Min.   :  0.000  
 1st Qu.:0.05208   1st Qu.:0.9585   1st Qu.:  0.086   1st Qu.:  0.262  
 Median :0.05208   Median :0.9585   Median :  0.104   Median :  0.326  
 Mean   :0.05208   Mean   :0.9585   Mean   :  0.164   Mean   :  0.488  
 3rd Qu.:0.05208   3rd Qu.:0.9585   3rd Qu.:  0.139   3rd Qu.:  0.436  
 Max.   :0.05208   Max.   :0.9585   Max.   :219.163   Max.   :246.949  
                                    NA's   :24757     NA's   :24757    
 TD_Mi_SSHG_q5    TD_Mi_SSHG_q95     TD_Mi_Mean      TD_Mi_Mean_F   
 Min.   :  0.00   Min.   :  0.00   Min.   :0.3076   Min.   :0.2318  
 1st Qu.:  0.09   1st Qu.:  0.25   1st Qu.:0.3076   1st Qu.:0.2318  
 Median :  0.11   Median :  0.31   Median :0.3076   Median :0.2318  
 Mean   :  0.18   Mean   :  0.47   Mean   :0.3076   Mean   :0.2318  
 3rd Qu.:  0.15   3rd Qu.:  0.42   3rd Qu.:0.3076   3rd Qu.:0.2318  
 Max.   :250.66   Max.   :250.66   Max.   :0.3076   Max.   :0.2318  
 NA's   :35629    NA's   :35629                                     
 TD_Mi_SS_Mean     TD_Mi_SS_Mean_F   TD_Mi_SSHG_Mean  TD_Mi_SSHG_Mean_F
 Min.   :  0.000   Min.   :  0.000   Min.   :  0.00   Min.   :  0.00   
 1st Qu.:  0.172   1st Qu.:  0.166   1st Qu.:  0.17   1st Qu.:  0.16   
 Median :  0.212   Median :  0.207   Median :  0.21   Median :  0.21   
 Mean   :  0.307   Mean   :  0.291   Mean   :  0.31   Mean   :  0.29   
 3rd Qu.:  0.267   3rd Qu.:  0.260   3rd Qu.:  0.27   3rd Qu.:  0.26   
 Max.   :219.163   Max.   :219.163   Max.   :250.66   Max.   :250.66   
 NA's   :24757     NA's   :27919     NA's   :35629    NA's   :44458    
   TD_Mi_Med       TD_Mi_Med_F      TD_Mi_SS_Med     TD_Mi_SS_Med_F   
 Min.   :0.1977   Min.   :0.1977   Min.   :  0.000   Min.   :  0.000  
 1st Qu.:0.1977   1st Qu.:0.1977   1st Qu.:  0.146   1st Qu.:  0.146  
 Median :0.1977   Median :0.1977   Median :  0.196   Median :  0.196  
 Mean   :0.1977   Mean   :0.1977   Mean   :  0.288   Mean   :  0.282  
 3rd Qu.:0.1977   3rd Qu.:0.1977   3rd Qu.:  0.265   3rd Qu.:  0.265  
 Max.   :0.1977   Max.   :0.1977   Max.   :219.163   Max.   :219.163  
                                   NA's   :24757     NA's   :27919    
 TD_Mi_SSHG_Med   TD_Mi_SSHG_Med_F   TD_Mi_Cnt        TD_Mi_Cnt_F     
 Min.   :  0.00   Min.   :  0.00   Min.   :2486795   Min.   :2387406  
 1st Qu.:  0.14   1st Qu.:  0.14   1st Qu.:2486795   1st Qu.:2387406  
 Median :  0.20   Median :  0.20   Median :2486795   Median :2387406  
 Mean   :  0.29   Mean   :  0.28   Mean   :2486795   Mean   :2387406  
 3rd Qu.:  0.27   3rd Qu.:  0.27   3rd Qu.:2486795   3rd Qu.:2387406  
 Max.   :250.66   Max.   :250.66   Max.   :2486795   Max.   :2387406  
 NA's   :35629    NA's   :44458                                       
  TD_Mi_SS_Cnt    TD_Mi_SS_Cnt_F   TD_Mi_SSHG_Cnt   TD_Mi_SSHG_Cnt_F
 Min.   :   0.0   Min.   :   0.0   Min.   :  0.00   Min.   :  0.00  
 1st Qu.: 163.0   1st Qu.: 146.0   1st Qu.: 26.00   1st Qu.: 22.00  
 Median : 280.0   Median : 252.0   Median : 45.00   Median : 39.00  
 Mean   : 347.4   Mean   : 312.7   Mean   : 57.27   Mean   : 50.85  
 3rd Qu.: 456.0   3rd Qu.: 411.0   3rd Qu.: 75.00   3rd Qu.: 67.00  
 Max.   :1543.0   Max.   :1388.0   Max.   :663.00   Max.   :595.00  
                                                                    
 TravelTime_Sec      TT_Sec_q2    TT_Sec_q98   TT_Sec_SS_q5      TT_Sec_SS_q95     
 Min.   :    1.0   Min.   :10   Min.   :349   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   25.0   1st Qu.:10   1st Qu.:349   1st Qu.:   15.00   1st Qu.:   48.00  
 Median :   39.0   Median :10   Median :349   Median :   22.00   Median :   80.05  
 Mean   :  104.9   Mean   :10   Mean   :349   Mean   :   61.26   Mean   :  183.28  
 3rd Qu.:   72.0   3rd Qu.:10   3rd Qu.:349   3rd Qu.:   34.00   3rd Qu.:  134.60  
 Max.   :60750.0   Max.   :10   Max.   :349   Max.   :60750.00   Max.   :60750.00  
 NA's   :6641                                 NA's   :6531       NA's   :6531      
 TT_Sec_SSHG_q5     TT_Sec_SSHG_q95     TT_Sec_Mean    TT_Sec_Mean_F  
 Min.   :    1.00   Min.   :    1.00   Min.   :104.9   Min.   :56.61  
 1st Qu.:   16.00   1st Qu.:   43.80   1st Qu.:104.9   1st Qu.:56.61  
 Median :   23.40   Median :   72.95   Median :104.9   Median :56.61  
 Mean   :   67.33   Mean   :  169.21   Mean   :104.9   Mean   :56.61  
 3rd Qu.:   36.70   3rd Qu.:  123.65   3rd Qu.:104.9   3rd Qu.:56.61  
 Max.   :60750.00   Max.   :60750.00   Max.   :104.9   Max.   :56.61  
 NA's   :6535       NA's   :6535                                      
 TT_Sec_SS_Mean     TT_Sec_SS_Mean_F   TT_Sec_SSHG_Mean   TT_Sec_SSHG_Mean_F
 Min.   :    1.00   Min.   :    1.00   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   29.06   1st Qu.:   27.54   1st Qu.:   28.38   1st Qu.:   27.21  
 Median :   44.16   Median :   41.91   Median :   43.38   Median :   41.48  
 Mean   :  104.88   Mean   :   91.34   Mean   :  104.88   Mean   :   93.53  
 3rd Qu.:   73.30   3rd Qu.:   69.25   3rd Qu.:   72.93   3rd Qu.:   70.12  
 Max.   :60750.00   Max.   :60750.00   Max.   :60750.00   Max.   :60750.00  
 NA's   :6531       NA's   :10519      NA's   :6535       NA's   :12811     
   TT_Sec_Med  TT_Sec_Med_F TT_Sec_SS_Med      TT_Sec_SS_Med_F   
 Min.   :39   Min.   :39    Min.   :    1.00   Min.   :    1.00  
 1st Qu.:39   1st Qu.:39    1st Qu.:   26.00   1st Qu.:   26.00  
 Median :39   Median :39    Median :   39.00   Median :   39.00  
 Mean   :39   Mean   :39    Mean   :   91.55   Mean   :   84.82  
 3rd Qu.:39   3rd Qu.:39    3rd Qu.:   65.00   3rd Qu.:   65.00  
 Max.   :39   Max.   :39    Max.   :60750.00   Max.   :60750.00  
                            NA's   :6531       NA's   :10519     
 TT_Sec_SSHG_Med    TT_Sec_SSHG_Med_F    TT_Sec_Cnt       TT_Sec_Cnt_F    
 Min.   :    1.00   Min.   :    1.00   Min.   :2802888   Min.   :2705189  
 1st Qu.:   26.00   1st Qu.:   26.00   1st Qu.:2802888   1st Qu.:2705189  
 Median :   39.00   Median :   38.50   Median :2802888   Median :2705189  
 Mean   :   94.94   Mean   :   88.44   Mean   :2802888   Mean   :2705189  
 3rd Qu.:   67.00   3rd Qu.:   66.50   3rd Qu.:2802888   3rd Qu.:2705189  
 Max.   :60750.00   Max.   :60750.00   Max.   :2802888   Max.   :2705189  
 NA's   :6535       NA's   :12811                                         
 TT_Sec_SS_Cnt    TT_Sec_SS_Cnt_F  TT_Sec_SSHG_Cnt  TT_Sec_SSHG_Cnt_F
 Min.   :   0.0   Min.   :   0.0   Min.   :  0.00   Min.   :  0.00   
 1st Qu.: 194.0   1st Qu.: 177.0   1st Qu.: 29.00   1st Qu.: 26.00   
 Median : 310.0   Median : 282.0   Median : 51.00   Median : 46.00   
 Mean   : 384.4   Mean   : 349.8   Mean   : 63.46   Mean   : 57.09   
 3rd Qu.: 497.0   3rd Qu.: 452.0   3rd Qu.: 83.00   3rd Qu.: 74.00   
 Max.   :1664.0   Max.   :1523.0   Max.   :691.00   Max.   :634.00   
                                                                     
 TravelTime_Hr       TT_Hr_q2          TT_Hr_q98        TT_Hr_SS_q5    
 Min.   : 0.000   Min.   :0.002778   Min.   :0.09694   Min.   : 0.000  
 1st Qu.: 0.007   1st Qu.:0.002778   1st Qu.:0.09694   1st Qu.: 0.004  
 Median : 0.011   Median :0.002778   Median :0.09694   Median : 0.006  
 Mean   : 0.029   Mean   :0.002778   Mean   :0.09694   Mean   : 0.017  
 3rd Qu.: 0.020   3rd Qu.:0.002778   3rd Qu.:0.09694   3rd Qu.: 0.009  
 Max.   :16.875   Max.   :0.002778   Max.   :0.09694   Max.   :16.875  
 NA's   :6641                                          NA's   :6531    
  TT_Hr_SS_q95    TT_Hr_SSHG_q5    TT_Hr_SSHG_q95     TT_Hr_Mean     
 Min.   : 0.000   Min.   : 0.000   Min.   : 0.000   Min.   :0.02913  
 1st Qu.: 0.013   1st Qu.: 0.004   1st Qu.: 0.012   1st Qu.:0.02913  
 Median : 0.022   Median : 0.006   Median : 0.020   Median :0.02913  
 Mean   : 0.051   Mean   : 0.019   Mean   : 0.047   Mean   :0.02913  
 3rd Qu.: 0.037   3rd Qu.: 0.010   3rd Qu.: 0.034   3rd Qu.:0.02913  
 Max.   :16.875   Max.   :16.875   Max.   :16.875   Max.   :0.02913  
 NA's   :6531     NA's   :6535     NA's   :6535                      
  TT_Hr_Mean_F     TT_Hr_SS_Mean    TT_Hr_SS_Mean_F  TT_Hr_SSHG_Mean 
 Min.   :0.01573   Min.   : 0.000   Min.   : 0.000   Min.   : 0.000  
 1st Qu.:0.01573   1st Qu.: 0.008   1st Qu.: 0.008   1st Qu.: 0.008  
 Median :0.01573   Median : 0.012   Median : 0.012   Median : 0.012  
 Mean   :0.01573   Mean   : 0.029   Mean   : 0.025   Mean   : 0.029  
 3rd Qu.:0.01573   3rd Qu.: 0.020   3rd Qu.: 0.019   3rd Qu.: 0.020  
 Max.   :0.01573   Max.   :16.875   Max.   :16.875   Max.   :16.875  
                   NA's   :6531     NA's   :10532    NA's   :6535    
 TT_Hr_SSHG_Mean_F   TT_Hr_Med        TT_Hr_Med_F       TT_Hr_SS_Med   
 Min.   : 0.000    Min.   :0.01083   Min.   :0.01083   Min.   : 0.000  
 1st Qu.: 0.008    1st Qu.:0.01083   1st Qu.:0.01083   1st Qu.: 0.007  
 Median : 0.012    Median :0.01083   Median :0.01083   Median : 0.011  
 Mean   : 0.026    Mean   :0.01083   Mean   :0.01083   Mean   : 0.025  
 3rd Qu.: 0.019    3rd Qu.:0.01083   3rd Qu.:0.01083   3rd Qu.: 0.018  
 Max.   :16.875    Max.   :0.01083   Max.   :0.01083   Max.   :16.875  
 NA's   :12895                                         NA's   :6531    
 TT_Hr_SS_Med_F   TT_Hr_SSHG_Med   TT_Hr_SSHG_Med_F   TT_Hr_Cnt      
 Min.   : 0.000   Min.   : 0.000   Min.   : 0.000   Min.   :2802888  
 1st Qu.: 0.007   1st Qu.: 0.007   1st Qu.: 0.007   1st Qu.:2802888  
 Median : 0.011   Median : 0.011   Median : 0.011   Median :2802888  
 Mean   : 0.024   Mean   : 0.026   Mean   : 0.025   Mean   :2802888  
 3rd Qu.: 0.018   3rd Qu.: 0.019   3rd Qu.: 0.018   3rd Qu.:2802888  
 Max.   :16.875   Max.   :16.875   Max.   :16.875   Max.   :2802888  
 NA's   :10532    NA's   :6535     NA's   :12895                     
  TT_Hr_Cnt_F       TT_Hr_SS_Cnt    TT_Hr_SS_Cnt_F   TT_Hr_SSHG_Cnt  
 Min.   :2705189   Min.   :   0.0   Min.   :   0.0   Min.   :  0.00  
 1st Qu.:2705189   1st Qu.: 194.0   1st Qu.: 176.0   1st Qu.: 29.00  
 Median :2705189   Median : 310.0   Median : 282.0   Median : 51.00  
 Mean   :2705189   Mean   : 384.4   Mean   : 349.6   Mean   : 63.46  
 3rd Qu.:2705189   3rd Qu.: 497.0   3rd Qu.: 452.0   3rd Qu.: 83.00  
 Max.   :2705189   Max.   :1664.0   Max.   :1523.0   Max.   :691.00  
                                                                     
 TT_Hr_SSHG_Cnt_F  SpeedAvg_Mph    
 Min.   :  0.00   Min.   :    0.0  
 1st Qu.: 26.00   1st Qu.:   10.1  
 Median : 46.00   Median :   16.7  
 Mean   : 57.05   Mean   :   26.5  
 3rd Qu.: 74.00   3rd Qu.:   31.2  
 Max.   :634.00   Max.   :22924.1  
                  NA's   :322762   

Investigation of TravelDistance_Mi.

View(TravDistMi_Pctiles): 99% of TravelDistance_Mi are about 1 mile or less…but some weird TravelDistance_Mi values (e.g., 584 miles traveled) exist.

Investigation of TravelDistance_Mi.

Why are some TravelDistance_Mi “NA”? It looks like partially because the records are the first trip of the day (for that bus), so I purposefully set the distance to “NA”. Another reason is due to the odometer recording a value less than the previous odometer recording. In most cases, I have no explanation for this - though I have observed about 67% of all instances where TravelDistance_Mi is NA (other than because it’s the first record of the day) are instances where DirChange2 is “Change”. This is weird and should be asked to WMATA.

Investigation of TravelDistance_Mi.

These records are NA becuase the current record odometer is less than the previous record odometer. Theoretically, this should NOT happen. Me: it appears that about 67% of all instances where TravelDistance_Mi is NA (other than because it’s th first record of the day) are instances where DirChange2 is “Change”. This is weird and should be asked to WMATA.

View(filter(AllDays_NewOrder,
            between(RowNum_OG, 194, 214) | # 204
              between(RowNum_OG, 440, 460) | # 450
              between(RowNum_OG, 478, 498) | # 488
              between(RowNum_OG, 510, 530) # 520
           )
    )
TestTable <- filter(AllDays_NewOrder,
                    BusDay_EventNum != 1
                   ) %>% 
  mutate(TravelDistance_NA = as.factor(ifelse(is.na(TravelDistance_Mi),
                                              "True",
                                              "False"
                                             )
                                      )
        ) %>%
  group_by(DirChange2, TravelDistance_NA) %>%
  summarise(TravDistMi_NACnts = n()
           )
# TestTable
TestTable_Spread <- as.data.frame(spread(TestTable,
                                         TravelDistance_NA,
                                         TravDistMi_NACnts
                                        )
                                 ) %>% 
  select(False,
         True
        )
row.names(TestTable_Spread) <- c("Change", "Same")
# str(TestTable_Spread)
# TestTable_Spread
prop.table(as.table(as.matrix(TestTable_Spread)
                   ),
           1
          )
           False      True
Change 0.8298069 0.1701931
Same   0.8884570 0.1115430
prop.table(as.table(as.matrix(TestTable_Spread)
                   ),
           2
          )
            False       True
Change 0.02020231 0.03258635
Same   0.97979769 0.96741365

Investigation of TravelDistance_Mi.

Let’s look at just the TravelDistance_Mi values that are NOT “NA”.

rm(TestTable)
rm(TestTable_Spread)
TravelDistance_Mi_NoNA <- filter(AllDays_NewOrder,
                                 # TravelDistance_Mi != 0 &
                                 !is.na(TravelDistance_Mi)
                                )
dim(AllDays_NewOrder)
[1] 2809529     113
dim(TravelDistance_Mi_NoNA)
[1] 2486795     113
nrow(AllDays_NewOrder) - nrow(TravelDistance_Mi_NoNA)
[1] 322734
str(TravelDistance_Mi_NoNA)
'data.frame':   2486795 obs. of  113 variables:
 $ RowNum_OG             : int  3 4 5 6 7 9 10 11 12 13 ...
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID          : chr  "5004572--5004573" "5004573--5002210" "5002210--5002209" "5002209--5000070" ...
 $ BusDay_EventNum       : int  2 3 4 5 6 7 8 9 10 11 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 6 6 6 6 6 ...
 $ DirChange2            : Factor w/ 2 levels "Change","Same": 2 2 2 2 2 1 2 2 2 2 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  6 3 2 8 1 2 3 4 2 6 ...
 $ Start_ID              : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Start_Desc            : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ StopID_Clean          : chr  "5004573" "5002210" "5002209" "5000070" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc             : chr  "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" "FRANCONIA-SPRGFLD STA. + BUS BAY D" ...
 $ Event_Type            : int  4 4 4 3 3 4 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 1 1 3 3 3 3 3 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min        : int  9 10 10 13 14 21 21 23 23 26 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:09:47" "2016-10-03 06:10:24" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:09:47" "2016-10-03 06:10:24" ...
 $ Dwell_Time            : int  0 0 0 0 104 0 0 0 0 0 ...
 $ Dwell_Time2           : num  0 0 0 0 104 0 0 0 0 0 ...
 $ Delta_Time            : int  24 165 25 73 719 74 76 63 69 165 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  97 276 15 119 100 274 104 241 274 1 ...
 $ Odometer_Distance     : int  45139 46418 50115 51074 51303 55633 56163 56285 57262 58363 ...
 $ Odometer_Distance_Lag1: int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Mi  : num  8.55 8.79 9.49 9.67 9.72 ...
 $ TravelDistance_Ft     : int  1596 1279 3697 959 229 4330 530 122 977 1101 ...
 $ TravelDistance_Mi     : num  0.3023 0.2422 0.7002 0.1816 0.0434 ...
 $ TravelDistance_Mi_Hvrs: num  0.15 0.105 0.165 0.832 0.068 ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TD_Mi_SS_q5           : num  0.025246 0.242235 0.732434 0.079432 0.000436 ...
 $ TD_Mi_SS_q95          : num  0.626 0.242 1.008 0.176 10.435 ...
 $ TD_Mi_SSHG_q5         : num  0.09956 0.24223 0.70019 0.18163 0.00269 ...
 $ TD_Mi_SSHG_q95        : num  0.627 0.242 0.7 0.182 0.497 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_SS_Mean         : num  0.437 0.242 0.908 0.128 1.166 ...
 $ TD_Mi_SS_Mean_F       : num  0.457 0.242 0.977 NaN 0.226 ...
 $ TD_Mi_SSHG_Mean       : num  0.442 0.242 0.7 0.182 0.232 ...
 $ TD_Mi_SSHG_Mean_F     : num  0.491 0.242 0.7 0.182 0.228 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_SS_Med          : num  0.5116 0.2422 0.9616 0.1278 0.0426 ...
 $ TD_Mi_SS_Med_F        : num  0.5116 0.2422 1.0081 NA 0.0426 ...
 $ TD_Mi_SSHG_Med        : num  0.512 0.242 0.7 0.182 0.108 ...
 $ TD_Mi_SSHG_Med_F      : num  0.512 0.242 0.7 0.182 0.108 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TD_Mi_SS_Cnt          : int  14 1 4 2 87 22 118 91 11 2 ...
 $ TD_Mi_SS_Cnt_F        : int  12 1 3 0 77 18 106 81 9 0 ...
 $ TD_Mi_SSHG_Cnt        : int  7 1 1 1 23 6 29 28 3 1 ...
 $ TD_Mi_SSHG_Cnt_F      : int  5 1 1 1 19 4 25 24 1 1 ...
 $ TravelTime_Sec        : num  180 37 25 190 29 288 52 76 8 189 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Sec_SS_q5          : num  11.9 37 30.5 172.9 10 ...
 $ TT_Sec_SS_q95         : num  346.3 37 75.8 189.1 1737.2 ...
 $ TT_Sec_SSHG_q5        : num  59.6 37 25 190 11.6 236 51.5 55 8.8 189 ...
 $ TT_Sec_SSHG_q95       : num  276 37 25 190 675 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_SS_Mean        : num  215.8 37 58.2 181 585.3 ...
 $ TT_Sec_SS_Mean_F      : num  218.9 37 65.5 NaN 249.3 ...
 $ TT_Sec_SSHG_Mean      : num  202 37 25 190 257 ...
 $ TT_Sec_SSHG_Mean_F    : num  226 37 25 190 244 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_SS_Med         : num  223.5 37 65.5 181 33 ...
 $ TT_Sec_SS_Med_F       : num  223.5 37 65.5 NA 32 ...
 $ TT_Sec_SSHG_Med       : num  219 37 25 190 134 286 60 65 16 189 ...
 $ TT_Sec_SSHG_Med_F     : num  219 37 25 190 134 286 60 65 16 189 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Sec_SS_Cnt         : int  14 1 4 2 173 22 141 141 11 2 ...
 $ TT_Sec_SS_Cnt_F       : int  12 1 2 0 156 18 127 128 9 0 ...
 $ TT_Sec_SSHG_Cnt       : int  7 1 1 1 35 6 36 35 3 1 ...
 $ TT_Sec_SSHG_Cnt_F     : int  5 1 1 1 31 4 32 32 1 1 ...
 $ TravelTime_Hr         : num  0.05 0.01028 0.00694 0.05278 0.00806 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TT_Hr_SS_q5           : num  0.00331 0.01028 0.00849 0.04803 0.00278 ...
 $ TT_Hr_SS_q95          : num  0.0962 0.0103 0.0211 0.0525 0.4826 ...
 $ TT_Hr_SSHG_q5         : num  0.01656 0.01028 0.00694 0.05278 0.00322 ...
 $ TT_Hr_SSHG_q95        : num  0.07653 0.01028 0.00694 0.05278 0.18739 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_SS_Mean         : num  0.0599 0.0103 0.0162 0.0503 0.1626 ...
 $ TT_Hr_SS_Mean_F       : num  0.0608 0.0103 0.0182 NaN 0.0692 ...
 $ TT_Hr_SSHG_Mean       : num  0.05615 0.01028 0.00694 0.05278 0.0715 ...
  [list output truncated]
summary(TravelDistance_Mi_NoNA)
   RowNum_OG       group      StartStop_ID       BusDay_EventNum      Bus_ID    
 Min.   :      3   1:496190   Length:2486795     Min.   :   2.0   Min.   :  11  
 1st Qu.: 786568   2:497932   Class :character   1st Qu.: 115.0   1st Qu.:2923  
 Median :1590497   3:501611   Mode  :character   Median : 251.0   Median :6202  
 Mean   :1578192   4:495069                      Mean   : 293.2   Mean   :5431  
 3rd Qu.:2351264   5:495993                      3rd Qu.: 431.0   3rd Qu.:7113  
 Max.   :3119443                                 Max.   :1344.0   Max.   :8105  
                                                                                
    Route              RouteAlt       DirChange2      Route_Direction  
 Length:2486795     2      :994645   Change:  50239   SOUTH   :667198  
 Class :character   1      :943279   Same  :2436556   NORTH   :662471  
 Mode  :character   3      :229032                    WEST    :565616  
                    4      :117090                    EAST    :543386  
                    5      : 67811                    LOOP    : 33484  
                    6      : 51391                    CLOCKWIS:  7012  
                    (Other): 83547                    (Other) :  7628  
 Stop_Sequence      Start_ID          Start_Desc        StopID_Clean      
 Min.   :  1.00   Length:2486795     Length:2486795     Length:2486795    
 1st Qu.: 12.00   Class :character   Class :character   Class :character  
 Median : 24.00   Mode  :character   Mode  :character   Mode  :character  
 Mean   : 27.13                                                           
 3rd Qu.: 39.00                                                           
 Max.   :104.00                                                           
                                                                          
 StopID_Indicator  Stop_Desc           Event_Type   
 ID_Bad:  14271   Length:2486795     Min.   :3.000  
 ID_OK :2472524   Class :character   1st Qu.:3.000  
                  Mode  :character   Median :4.000  
                                     Mean   :3.626  
                                     3rd Qu.:4.000  
                                     Max.   :5.000  
                                                    
                                          Event_Description   Event_Time_Yr 
 Serviced Stop                                     : 930934   Min.   :2016  
 Unknown Stop                                      :   1794   1st Qu.:2016  
 UnServiced Stop                                   :1554067   Median :2016  
                                                              Mean   :2016  
                                                              3rd Qu.:2016  
                                                              Max.   :2016  
                                                                            
 Event_Time_Mth Event_Time_Date Event_Time_Day Event_Time_Hr    Event_Time_HrGroup
 Min.   :10     Min.   :3.000   Sun  :     0   Min.   : 0.00   Group6_8  :538348  
 1st Qu.:10     1st Qu.:4.000   Mon  :496190   1st Qu.: 8.00   Group15_17:497156  
 Median :10     Median :5.000   Tues :497932   Median :13.00   Group18_20:408957  
 Mean   :10     Mean   :4.999   Wed  :501611   Mean   :12.99   Group9_11 :351804  
 3rd Qu.:10     3rd Qu.:6.000   Thurs:495069   3rd Qu.:18.00   Group12_14:314050  
 Max.   :10     Max.   :7.000   Fri  :495993   Max.   :23.00   Group21_23:217259  
                                Sat  :     0                   (Other)   :159221  
 Event_Time_Min    Event_Time                  Departure_Time               
 Min.   : 0.00   Min.   :2016-10-03 00:00:09   Min.   :2016-10-03 00:00:09  
 1st Qu.:14.00   1st Qu.:2016-10-04 08:35:52   1st Qu.:2016-10-04 08:35:59  
 Median :29.00   Median :2016-10-05 13:46:00   Median :2016-10-05 13:46:06  
 Mean   :29.43   Mean   :2016-10-05 13:27:43   Mean   :2016-10-05 13:27:49  
 3rd Qu.:44.00   3rd Qu.:2016-10-06 17:57:32   3rd Qu.:2016-10-06 17:57:39  
 Max.   :59.00   Max.   :2016-10-07 23:59:59   Max.   :2016-10-08 00:12:31  
                                                                            
   Dwell_Time       Dwell_Time2         Delta_Time         Latitude    
 Min.   :   0.00   Min.   :   0.000   Min.   :-5606.0   Min.   : 0.00  
 1st Qu.:   0.00   1st Qu.:   0.000   1st Qu.:   16.0   1st Qu.:38.86  
 Median :   0.00   Median :   0.000   Median :  160.0   Median :38.90  
 Mean   :  11.86   Mean   :   5.994   Mean   :  274.1   Mean   :38.91  
 3rd Qu.:   4.00   3rd Qu.:   4.000   3rd Qu.:  402.0   3rd Qu.:38.96  
 Max.   :6205.00   Max.   :6205.000   Max.   : 9426.0   Max.   :39.19  
                                                                       
   Longitude         Heading      Odometer_Distance  Odometer_Distance_Lag1
 Min.   :-77.45   Min.   :  0.0   Min.   :       1   Min.   :       0      
 1st Qu.:-77.07   1st Qu.: 89.0   1st Qu.:  200268   1st Qu.:  198635      
 Median :-77.01   Median :180.0   Median :  394700   Median :  393026      
 Mean   :-77.02   Mean   :176.7   Mean   :  443225   Mean   :  441601      
 3rd Qu.:-76.97   3rd Qu.:269.0   3rd Qu.:  633936   3rd Qu.:  632313      
 Max.   :  0.00   Max.   :360.0   Max.   :11108034   Max.   :10853226      
                                                                           
 Odometer_Distance_Mi TravelDistance_Ft TravelDistance_Mi   TravelDistance_Mi_Hvrs
 Min.   :   0.0002    Min.   :      1   Min.   :  0.00019   Min.   : 0.0000       
 1st Qu.:  37.9295    1st Qu.:    699   1st Qu.:  0.13239   1st Qu.: 0.1034       
 Median :  74.7538    Median :   1044   Median :  0.19773   Median : 0.1378       
 Mean   :  83.9442    Mean   :   1624   Mean   :  0.30760   Mean   : 0.1918       
 3rd Qu.: 120.0635    3rd Qu.:   1518   3rd Qu.:  0.28750   3rd Qu.: 0.1828       
 Max.   :2103.7943    Max.   :1323464   Max.   :250.65606   Max.   :24.1507       
                                                                                  
    TD_Mi_q2         TD_Mi_q98       TD_Mi_SS_q5         TD_Mi_SS_q95      
 Min.   :0.05208   Min.   :0.9585   Min.   :  0.00019   Min.   :  0.00019  
 1st Qu.:0.05208   1st Qu.:0.9585   1st Qu.:  0.08848   1st Qu.:  0.25878  
 Median :0.05208   Median :0.9585   Median :  0.10608   Median :  0.32239  
 Mean   :0.05208   Mean   :0.9585   Mean   :  0.16872   Mean   :  0.47949  
 3rd Qu.:0.05208   3rd Qu.:0.9585   3rd Qu.:  0.13977   3rd Qu.:  0.42822  
 Max.   :0.05208   Max.   :0.9585   Max.   :219.16288   Max.   :246.94938  
                                                                           
 TD_Mi_SSHG_q5       TD_Mi_SSHG_q95        TD_Mi_Mean      TD_Mi_Mean_F   
 Min.   :  0.00019   Min.   :  0.00019   Min.   :0.3076   Min.   :0.2318  
 1st Qu.:  0.09167   1st Qu.:  0.24754   1st Qu.:0.3076   1st Qu.:0.2318  
 Median :  0.11395   Median :  0.31174   Median :0.3076   Median :0.2318  
 Mean   :  0.18528   Mean   :  0.46625   Mean   :0.3076   Mean   :0.2318  
 3rd Qu.:  0.15093   3rd Qu.:  0.41899   3rd Qu.:0.3076   3rd Qu.:0.2318  
 Max.   :250.65606   Max.   :250.65606   Max.   :0.3076   Max.   :0.2318  
                                                                          
 TD_Mi_SS_Mean       TD_Mi_SS_Mean_F    TD_Mi_SSHG_Mean     TD_Mi_SSHG_Mean_F
 Min.   :  0.00019   Min.   :  0.0002   Min.   :  0.00019   Min.   :  0.000  
 1st Qu.:  0.17129   1st Qu.:  0.1663   1st Qu.:  0.16760   1st Qu.:  0.163  
 Median :  0.21082   Median :  0.2058   Median :  0.20965   Median :  0.206  
 Mean   :  0.30760   Mean   :  0.2916   Mean   :  0.30760   Mean   :  0.294  
 3rd Qu.:  0.26422   3rd Qu.:  0.2582   3rd Qu.:  0.26616   3rd Qu.:  0.262  
 Max.   :219.16288   Max.   :219.1629   Max.   :250.65606   Max.   :250.656  
                     NA's   :2678                           NA's   :4904     
   TD_Mi_Med       TD_Mi_Med_F      TD_Mi_SS_Med       TD_Mi_SS_Med_F    
 Min.   :0.1977   Min.   :0.1977   Min.   :  0.00019   Min.   :  0.0002  
 1st Qu.:0.1977   1st Qu.:0.1977   1st Qu.:  0.14602   1st Qu.:  0.1458  
 Median :0.1977   Median :0.1977   Median :  0.19470   Median :  0.1947  
 Mean   :0.1977   Mean   :0.1977   Mean   :  0.28931   Mean   :  0.2827  
 3rd Qu.:0.1977   3rd Qu.:0.1977   3rd Qu.:  0.26326   3rd Qu.:  0.2633  
 Max.   :0.1977   Max.   :0.1977   Max.   :219.16288   Max.   :219.1629  
                                                       NA's   :2678      
 TD_Mi_SSHG_Med      TD_Mi_SSHG_Med_F    TD_Mi_Cnt        TD_Mi_Cnt_F     
 Min.   :  0.00019   Min.   :  0.000   Min.   :2486795   Min.   :2387406  
 1st Qu.:  0.14403   1st Qu.:  0.144   1st Qu.:2486795   1st Qu.:2387406  
 Median :  0.19527   Median :  0.195   Median :2486795   Median :2387406  
 Mean   :  0.29152   Mean   :  0.285   Mean   :2486795   Mean   :2387406  
 3rd Qu.:  0.26657   3rd Qu.:  0.266   3rd Qu.:2486795   3rd Qu.:2387406  
 Max.   :250.65606   Max.   :250.656   Max.   :2486795   Max.   :2387406  
                     NA's   :4904                                         
  TD_Mi_SS_Cnt    TD_Mi_SS_Cnt_F   TD_Mi_SSHG_Cnt   TD_Mi_SSHG_Cnt_F
 Min.   :   1.0   Min.   :   0.0   Min.   :  1.00   Min.   :  0.00  
 1st Qu.: 178.0   1st Qu.: 160.0   1st Qu.: 28.00   1st Qu.: 24.00  
 Median : 295.0   Median : 266.0   Median : 48.00   Median : 42.00  
 Mean   : 363.3   Mean   : 327.1   Mean   : 60.01   Mean   : 53.31  
 3rd Qu.: 476.0   3rd Qu.: 428.0   3rd Qu.: 78.00   3rd Qu.: 70.00  
 Max.   :1543.0   Max.   :1388.0   Max.   :663.00   Max.   :595.00  
                                                                    
 TravelTime_Sec    TT_Sec_q2    TT_Sec_q98   TT_Sec_SS_q5      TT_Sec_SS_q95     
 Min.   :    1   Min.   :10   Min.   :349   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   24   1st Qu.:10   1st Qu.:349   1st Qu.:   15.00   1st Qu.:   47.00  
 Median :   38   Median :10   Median :349   Median :   21.00   Median :   77.75  
 Mean   :  100   Mean   :10   Mean   :349   Mean   :   57.38   Mean   :  176.22  
 3rd Qu.:   70   3rd Qu.:10   3rd Qu.:349   3rd Qu.:   32.00   3rd Qu.:  129.65  
 Max.   :54551   Max.   :10   Max.   :349   Max.   :54551.00   Max.   :54551.00  
 NA's   :28                                                                      
 TT_Sec_SSHG_q5     TT_Sec_SSHG_q95     TT_Sec_Mean    TT_Sec_Mean_F  
 Min.   :    1.00   Min.   :    1.00   Min.   :104.9   Min.   :56.61  
 1st Qu.:   15.20   1st Qu.:   42.70   1st Qu.:104.9   1st Qu.:56.61  
 Median :   22.50   Median :   70.55   Median :104.9   Median :56.61  
 Mean   :   62.94   Mean   :  161.25   Mean   :104.9   Mean   :56.61  
 3rd Qu.:   34.80   3rd Qu.:  119.60   3rd Qu.:104.9   3rd Qu.:56.61  
 Max.   :54551.00   Max.   :54551.00   Max.   :104.9   Max.   :56.61  
                                                                      
 TT_Sec_SS_Mean     TT_Sec_SS_Mean_F   TT_Sec_SSHG_Mean   TT_Sec_SSHG_Mean_F
 Min.   :    1.00   Min.   :    1.00   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   28.20   1st Qu.:   26.62   1st Qu.:   27.51   1st Qu.:   26.34  
 Median :   42.61   Median :   40.46   Median :   41.76   Median :   39.96  
 Mean   :   99.62   Mean   :   86.96   Mean   :   99.55   Mean   :   88.81  
 3rd Qu.:   69.71   3rd Qu.:   66.44   3rd Qu.:   70.02   3rd Qu.:   67.22  
 Max.   :54551.00   Max.   :54551.00   Max.   :54551.00   Max.   :54551.00  
                    NA's   :2603                          NA's   :3772      
   TT_Sec_Med  TT_Sec_Med_F TT_Sec_SS_Med      TT_Sec_SS_Med_F   
 Min.   :39   Min.   :39    Min.   :    1.00   Min.   :    1.00  
 1st Qu.:39   1st Qu.:39    1st Qu.:   25.00   1st Qu.:   25.00  
 Median :39   Median :39    Median :   37.00   Median :   37.00  
 Mean   :39   Mean   :39    Mean   :   86.88   Mean   :   80.62  
 3rd Qu.:39   3rd Qu.:39    3rd Qu.:   62.00   3rd Qu.:   62.00  
 Max.   :39   Max.   :39    Max.   :54551.00   Max.   :54551.00  
                                               NA's   :2603      
 TT_Sec_SSHG_Med    TT_Sec_SSHG_Med_F    TT_Sec_Cnt       TT_Sec_Cnt_F    
 Min.   :    1.00   Min.   :    1.00   Min.   :2802888   Min.   :2705189  
 1st Qu.:   25.00   1st Qu.:   25.00   1st Qu.:2802888   1st Qu.:2705189  
 Median :   37.00   Median :   37.00   Median :2802888   Median :2705189  
 Mean   :   90.07   Mean   :   83.87   Mean   :2802888   Mean   :2705189  
 3rd Qu.:   64.00   3rd Qu.:   64.00   3rd Qu.:2802888   3rd Qu.:2705189  
 Max.   :54551.00   Max.   :54551.00   Max.   :2802888   Max.   :2705189  
                    NA's   :3772                                          
 TT_Sec_SS_Cnt    TT_Sec_SS_Cnt_F  TT_Sec_SSHG_Cnt TT_Sec_SSHG_Cnt_F
 Min.   :   1.0   Min.   :   0.0   Min.   :  1.0   Min.   :  0.00   
 1st Qu.: 200.0   1st Qu.: 183.0   1st Qu.: 30.0   1st Qu.: 27.00   
 Median : 321.0   Median : 292.0   Median : 52.0   Median : 47.00   
 Mean   : 392.4   Mean   : 357.2   Mean   : 64.7   Mean   : 58.23   
 3rd Qu.: 509.0   3rd Qu.: 464.0   3rd Qu.: 84.0   3rd Qu.: 76.00   
 Max.   :1664.0   Max.   :1523.0   Max.   :691.0   Max.   :634.00   
                                                                    
 TravelTime_Hr          TT_Hr_q2          TT_Hr_q98        TT_Hr_SS_q5       
 Min.   : 0.000278   Min.   :0.002778   Min.   :0.09694   Min.   : 0.000278  
 1st Qu.: 0.006667   1st Qu.:0.002778   1st Qu.:0.09694   1st Qu.: 0.004167  
 Median : 0.010556   Median :0.002778   Median :0.09694   Median : 0.005833  
 Mean   : 0.027782   Mean   :0.002778   Mean   :0.09694   Mean   : 0.015938  
 3rd Qu.: 0.019444   3rd Qu.:0.002778   3rd Qu.:0.09694   3rd Qu.: 0.008889  
 Max.   :15.153056   Max.   :0.002778   Max.   :0.09694   Max.   :15.153056  
 NA's   :28                                                                  
  TT_Hr_SS_q95       TT_Hr_SSHG_q5       TT_Hr_SSHG_q95        TT_Hr_Mean     
 Min.   : 0.000278   Min.   : 0.000278   Min.   : 0.000278   Min.   :0.02913  
 1st Qu.: 0.013056   1st Qu.: 0.004222   1st Qu.: 0.011861   1st Qu.:0.02913  
 Median : 0.021597   Median : 0.006250   Median : 0.019597   Median :0.02913  
 Mean   : 0.048950   Mean   : 0.017485   Mean   : 0.044792   Mean   :0.02913  
 3rd Qu.: 0.036014   3rd Qu.: 0.009667   3rd Qu.: 0.033222   3rd Qu.:0.02913  
 Max.   :15.153056   Max.   :15.153056   Max.   :15.153056   Max.   :0.02913  
                                                                              
  TT_Hr_Mean_F     TT_Hr_SS_Mean       TT_Hr_SS_Mean_F   TT_Hr_SSHG_Mean    
 Min.   :0.01573   Min.   : 0.000278   Min.   : 0.0003   Min.   : 0.000278  
 1st Qu.:0.01573   1st Qu.: 0.007832   1st Qu.: 0.0074   1st Qu.: 0.007643  
 Median :0.01573   Median : 0.011836   Median : 0.0112   Median : 0.011600  
 Mean   :0.01573   Mean   : 0.027673   Mean   : 0.0242   Mean   : 0.027654  
 3rd Qu.:0.01573   3rd Qu.: 0.019363   3rd Qu.: 0.0185   3rd Qu.: 0.019450  
 Max.   :0.01573   Max.   :15.153056   Max.   :15.1531   Max.   :15.153056  
                                       NA's   :2612                         
 TT_Hr_SSHG_Mean_F   TT_Hr_Med        TT_Hr_Med_F       TT_Hr_SS_Med      
 Min.   : 0.000    Min.   :0.01083   Min.   :0.01083   Min.   : 0.000278  
 1st Qu.: 0.007    1st Qu.:0.01083   1st Qu.:0.01083   1st Qu.: 0.006944  
 Median : 0.011    Median :0.01083   Median :0.01083   Median : 0.010278  
 Mean   : 0.025    Mean   :0.01083   Mean   :0.01083   Mean   : 0.024132  
 3rd Qu.: 0.019    3rd Qu.:0.01083   3rd Qu.:0.01083   3rd Qu.: 0.017222  
 Max.   :15.153    Max.   :0.01083   Max.   :0.01083   Max.   :15.153056  
 NA's   :3842                                                             
 TT_Hr_SS_Med_F    TT_Hr_SSHG_Med      TT_Hr_SSHG_Med_F   TT_Hr_Cnt      
 Min.   : 0.0003   Min.   : 0.000278   Min.   : 0.000   Min.   :2802888  
 1st Qu.: 0.0069   1st Qu.: 0.006944   1st Qu.: 0.007   1st Qu.:2802888  
 Median : 0.0103   Median : 0.010278   Median : 0.010   Median :2802888  
 Mean   : 0.0224   Mean   : 0.025019   Mean   : 0.023   Mean   :2802888  
 3rd Qu.: 0.0172   3rd Qu.: 0.017778   3rd Qu.: 0.018   3rd Qu.:2802888  
 Max.   :15.1531   Max.   :15.153056   Max.   :15.153   Max.   :2802888  
 NA's   :2612                          NA's   :3842                      
  TT_Hr_Cnt_F       TT_Hr_SS_Cnt    TT_Hr_SS_Cnt_F TT_Hr_SSHG_Cnt  TT_Hr_SSHG_Cnt_F
 Min.   :2705189   Min.   :   1.0   Min.   :   0   Min.   :  1.0   Min.   :  0.00  
 1st Qu.:2705189   1st Qu.: 200.0   1st Qu.: 183   1st Qu.: 30.0   1st Qu.: 27.00  
 Median :2705189   Median : 321.0   Median : 292   Median : 52.0   Median : 47.00  
 Mean   :2705189   Mean   : 392.4   Mean   : 357   Mean   : 64.7   Mean   : 58.19  
 3rd Qu.:2705189   3rd Qu.: 509.0   3rd Qu.: 464   3rd Qu.: 84.0   3rd Qu.: 76.00  
 Max.   :2705189   Max.   :1664.0   Max.   :1523   Max.   :691.0   Max.   :634.00  
                                                                                   
  SpeedAvg_Mph     
 Min.   :    0.00  
 1st Qu.:   10.10  
 Median :   16.68  
 Mean   :   26.54  
 3rd Qu.:   31.17  
 Max.   :22924.09  
 NA's   :28        

Investigation of TravelDistance_Mi.

Let’s plot just the TravelDistance_Mi values that are NOT “NA”.

TravDistMi_HistDen <- ggplot(select(TravelDistance_Mi_NoNA,
                                    TravelDistance_Mi
                                   ),
                             aes(x = TravelDistance_Mi,
                                 y = ..density..
                                )
                            ) +
  geom_histogram(binwidth = 0.05, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(0, 1.5), ylim = c(0, 4.0)
                 ) +
  labs(title = "Variation in Distance Between Stops",
       x = "Travel Distance (miles)",
       y = "Density"
      )
TravDistMi_HistDen

Investigation of TravelDistance_Mi.

Looking at the extremely large TravelDistance_Mi values. Some (aprox 27%) of TravelDistance_Mi values > 1 mile are when the DirChange2 changes…but what about the other ~73%?

Investigation of TravelDistance_Mi.

Any relation with DirChange2? Doesn’t look as if this is so.

ExtremeTravDist <- filter(AllDays_NewOrder,
                          !is.na(TravelDistance_Mi)
                         ) %>% 
  mutate(TravDist_Extreme = ifelse(TravelDistance_Mi > 1.1587121212, # 1.1587121212 is the 99th percentile
                                   "True",
                                   "False"
                                  )
                          ) %>% 
  group_by(DirChange2, TravDist_Extreme) %>% 
  summarise(TravDistMI_ExtCnts = n()
           )
# ExtremeTravDist
ExtremeTravDist_Spread <- as.data.frame(spread(ExtremeTravDist,
                                               TravDist_Extreme,
                                               TravDistMI_ExtCnts
                                              )
                                       ) %>% 
  select(False,
         True
        )
row.names(ExtremeTravDist_Spread) <- c("Change", "Same")
# str(ExtremeTravDist_Spread)
# ExtremeTravDist_Spread
prop.table(as.table(as.matrix(ExtremeTravDist_Spread)
                   ),
           1
          )
            False       True
Change 0.76966102 0.23033898
Same   0.98944289 0.01055711
prop.table(as.table(as.matrix(ExtremeTravDist_Spread)
                   ),
           2
          )
            False       True
Change 0.01578567 0.31028288
Same   0.98421433 0.68971712

Investigation of TravelDistance_Mi.

Looking at specific buses and StartStop_ID.

Investigation of TravelDistance_Mi & TravelDistance_Mi_New.

If TravelDisntace_Mi is below the 5th percentile for that StartStop_ID, or if TravelDisntace_Mi is above the 95th percentile for that StartStop_ID, or if TravelDistance_Mi is NA (when the BusDay_EventNum !=1), consider this an outlier. In this case, replace the value with the mean for that StartStop_ID and HourGroup (TD_Mi_SSHG_Mean_F), or if there are not enough values at the HourGroup level, replace it with the mean for that StartStop_ID.

# View(tail(AllDays_NewOrder, 500))
AllDays_NewTravelDist <- 
  mutate(AllDays_NewOrder,
         TravelDistance_Mi_New = ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SSHG_Cnt_F >= 20,
                                        TD_Mi_SSHG_Mean_F,
                                 ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SSHG_Cnt_F < 20 &
                                          TD_Mi_SS_Cnt_F >= 20,
                                        TD_Mi_SS_Mean_F,
                                 ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SS_Cnt_F < 20 &
                                          TD_Mi_SS_Cnt >= 20,
                                        TD_Mi_SS_Mean,
                                 ifelse(is.na(TravelDistance_Mi) &
                                          BusDay_EventNum != 1 &
                                          TravelDistance_Mi_Hvrs != 0,
                                        TravelDistance_Mi_Hvrs,
                                 ifelse(is.na(TravelDistance_Mi) &
                                          BusDay_EventNum != 1 &
                                          TravelDistance_Mi_Hvrs == 0,
                                        TD_Mi_SS_Mean,
                                        TravelDistance_Mi
                                       ))))),
         TravelDistance_Mi_New_Label = 
           factor(ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SSHG_Cnt_F >= 20,
                         "TD_Mi_SSHG_Mean_F",
                  ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SSHG_Cnt_F < 20 &
                           TD_Mi_SS_Cnt_F >= 20,
                         "TD_Mi_SS_Mean_F",
                  ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SS_Cnt_F < 20 &
                           TD_Mi_SS_Cnt >= 20,
                         "TD_Mi_SS_Mean",
                  ifelse(is.na(TravelDistance_Mi) &
                           BusDay_EventNum != 1 &
                           TravelDistance_Mi_Hvrs != 0,
                         "TravelDistance_Mi_Hvrs",
                  ifelse(is.na(TravelDistance_Mi) &
                           BusDay_EventNum != 1 &
                           TravelDistance_Mi_Hvrs == 0,
                         "TD_Mi_SS_Mean",
                         "TravelDistance_Mi"
                        )))))
                 ),
         TravelDistance_Mi_NewHvrs = ifelse(!is.na(TravelDistance_Mi_Hvrs) &
                                              TravelDistance_Mi_Hvrs != 0 &
                                              (TravelDistance_Mi_New < TD_Mi_q2 |
                                                 TravelDistance_Mi_New > TD_Mi_q98
                                              ),
                                            TravelDistance_Mi_Hvrs,
                                            TravelDistance_Mi_New
                                           ),
         TravelDistance_Mi_NewHvrs_Label =
           factor(ifelse(!is.na(TravelDistance_Mi_Hvrs) &
                           TravelDistance_Mi_Hvrs != 0 &
                           (TravelDistance_Mi_New < TD_Mi_q2 |
                              TravelDistance_Mi_New > TD_Mi_q98
                           ),
                         "TravelDistance_Mi_Hvrs",
                         as.character(TravelDistance_Mi_New_Label)
                        )
                 )
        )
str(AllDays_NewTravelDist)
'data.frame':   2809529 obs. of  117 variables:
 $ RowNum_OG                      : int  1 3 4 5 6 7 9 10 11 12 ...
 $ group                          : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID                   : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ BusDay_EventNum                : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Bus_ID                         : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                          : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt                       : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ DirChange2                     : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 1 2 2 2 ...
 $ Route_Direction                : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence                  : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Start_ID                       : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc                     : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StopID_Clean                   : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator               : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc                      : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type                     : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description              : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time_Yr                  : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth                 : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date                : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day                 : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr                  : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup             : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min                 : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time                     : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time                 : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time                     : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Dwell_Time2                    : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time                     : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Latitude                       : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude                      : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading                        : int  199 97 276 15 119 100 274 104 241 274 ...
 $ Odometer_Distance              : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Lag1         : int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Odometer_Distance_Mi           : num  8.25 8.55 8.79 9.49 9.67 ...
 $ TravelDistance_Ft              : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi              : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs         : num  NA 0.15 0.105 0.165 0.832 ...
 $ TD_Mi_q2                       : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98                      : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TD_Mi_SS_q5                    : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95                   : num  NA 0.626 0.242 1.008 0.176 ...
 $ TD_Mi_SSHG_q5                  : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95                 : num  NA 0.627 0.242 0.7 0.182 ...
 $ TD_Mi_Mean                     : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F                   : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_SS_Mean                  : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F                : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SSHG_Mean                : num  NaN 0.442 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Mean_F              : num  NaN 0.491 0.242 0.7 0.182 ...
 $ TD_Mi_Med                      : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F                    : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_SS_Med                   : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F                 : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SSHG_Med                 : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Med_F               : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_Cnt                      : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F                    : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TD_Mi_SS_Cnt                   : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F                 : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TD_Mi_SSHG_Cnt                 : int  0 7 1 1 1 23 6 29 28 3 ...
 $ TD_Mi_SSHG_Cnt_F               : int  0 5 1 1 1 19 4 25 24 1 ...
 $ TravelTime_Sec                 : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TT_Sec_q2                      : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98                     : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Sec_SS_q5                   : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95                  : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Sec_SSHG_q5                 : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95                : num  NA 276 37 25 190 ...
 $ TT_Sec_Mean                    : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F                  : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_SS_Mean                 : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F               : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SSHG_Mean               : num  NaN 202 37 25 190 ...
 $ TT_Sec_SSHG_Mean_F             : num  NaN 226 37 25 190 ...
 $ TT_Sec_Med                     : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F                   : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_SS_Med                  : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F                : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SSHG_Med                : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_SSHG_Med_F              : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_Cnt                     : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F                   : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Sec_SS_Cnt                  : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F                : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Sec_SSHG_Cnt                : int  0 7 1 1 1 35 6 36 35 3 ...
 $ TT_Sec_SSHG_Cnt_F              : int  0 5 1 1 1 31 4 32 32 1 ...
 $ TravelTime_Hr                  : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ TT_Hr_q2                       : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98                      : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TT_Hr_SS_q5                    : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95                   : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TT_Hr_SSHG_q5                  : num  NA 0.01656 0.01028 0.00694 0.05278 ...
 $ TT_Hr_SSHG_q95                 : num  NA 0.07653 0.01028 0.00694 0.05278 ...
 $ TT_Hr_Mean                     : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F                   : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_SS_Mean                  : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F                : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SSHG_Mean                : num  NaN 0.05615 0.01028 0.00694 0.05278 ...
  [list output truncated]

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Quick summary and then correlation calculation.

summary(select(AllDays_NewTravelDist,
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.0     Min.   : 0.000         Min.   :  0.000      
 1st Qu.:  0.1     1st Qu.: 0.106         1st Qu.:  0.141      
 Median :  0.2     Median : 0.142         Median :  0.199      
 Mean   :  0.3     Mean   : 0.201         Mean   :  0.298      
 3rd Qu.:  0.3     3rd Qu.: 0.193         3rd Qu.:  0.276      
 Max.   :250.7     Max.   :24.407         Max.   :250.656      
 NA's   :322734    NA's   :6528           NA's   :6566         
 TravelDistance_Mi_NewHvrs
 Min.   : 0.000           
 1st Qu.: 0.142           
 Median : 0.199           
 Mean   : 0.259           
 3rd Qu.: 0.276           
 Max.   :36.236           
 NA's   :6566             
summary(select(filter(AllDays_NewTravelDist,
                      BusDay_EventNum != 1
                     ),
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.00    Min.   : 0.0000        Min.   :  0.00019    
 1st Qu.:  0.13    1st Qu.: 0.1055        1st Qu.:  0.14072    
 Median :  0.20    Median : 0.1424        Median :  0.19867    
 Mean   :  0.31    Mean   : 0.2008        Mean   :  0.29751    
 3rd Qu.:  0.29    3rd Qu.: 0.1935        3rd Qu.:  0.27633    
 Max.   :250.66    Max.   :24.4068        Max.   :250.65606    
 NA's   :316206                           NA's   :38           
 TravelDistance_Mi_NewHvrs
 Min.   : 0.00019         
 1st Qu.: 0.14205         
 Median : 0.19903         
 Mean   : 0.25859         
 3rd Qu.: 0.27557         
 Max.   :36.23636         
 NA's   :38               
cor(select(AllDays_NewTravelDist,
           TravelDistance_Mi,
           TravelDistance_Mi_Hvrs,
           TravelDistance_Mi_New,
           TravelDistance_Mi_NewHvrs
          ),
    use = "pairwise.complete.obs"
  )
                          TravelDistance_Mi TravelDistance_Mi_Hvrs
TravelDistance_Mi                 1.0000000              0.5447660
TravelDistance_Mi_Hvrs            0.5447660              1.0000000
TravelDistance_Mi_New             0.9513379              0.5837182
TravelDistance_Mi_NewHvrs         0.6005944              0.9005277
                          TravelDistance_Mi_New TravelDistance_Mi_NewHvrs
TravelDistance_Mi                     0.9513379                 0.6005944
TravelDistance_Mi_Hvrs                0.5837182                 0.9005277
TravelDistance_Mi_New                 1.0000000                 0.6346981
TravelDistance_Mi_NewHvrs             0.6346981                 1.0000000

Investigation of TravelDistance_Mi_NewHvrs_Label & TravelDistance_Mi_NewHvrs_Label.

Show how the labels changed.

group_by(AllDays_NewTravelDist,
         TravelDistance_Mi_New_Label,
         TravelDistance_Mi_NewHvrs_Label
        ) %>% 
  summarise(CntNum = n(),
            CntPct = format(CntNum / nrow(AllDays_NewTravelDist),
                            scientific = 9999
                           )
           ) %>% 
  arrange(desc(CntPct)
         )

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Graphing the two methods of calculating TravelDistance_Mi.

First, let’s get create a function to plot the liner model equation.

lm_eqn <- function(df, y, x){
  m <- lm(y ~ x, df)
  
  l <- list(a = format(coef(m)[1], digits = 2),
            b = format(abs(coef(m)[2]), digits = 2),
            s1 = ifelse(test = coef(m)[2] > 0,
                        yes = "+",
                        no = "-"
                       ),
            r2 = format(summary(m)$r.squared,
                        digits = 3
                       )
           )
  
  eq <- substitute(italic(y) == a~~s1~~b %.% italic(x)*","~~italic(r)^2~"="~r2,
                   l
                  )
  
  as.character(as.expression(eq)
              )             
}

Investigation of TravelDistance_Mi & TravelDistance_Mi_NewHvrs.

Scatter plot (using a 10% sample to making plotting time faster and to reduce un-needed data in the “same” splot).

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Graphing test with rbokeh.

TravDist_MiVsCalc_Bokeh <- figure(data = select(AllDays_NewTravelDist_10Pct,
                                                TravelDistance_Mi_NewHvrs,
                                                TravelDistance_Mi,
                                                DistMethod
                                               ),
                                  xlim = c(0, 1.5),
                                  ylim = c(0, 1.5),
                                  legend_location = "bottom_right"
                                 ) %>% 
  ly_points(x = TravelDistance_Mi,
            y = TravelDistance_Mi_NewHvrs,
            color = DistMethod,
            hover = c(TravelDistance_Mi_NewHvrs, TravelDistance_Mi, DistMethod)
           ) %>% 
  ly_abline(a = 0, b = 1, color = "red")
TravDist_MiVsCalc_Bokeh

Investigation of TravelDistance_Mi_New.

~11% of rides are still showing as less than 0.1 miles of TravelDistance_Mi_New.

TravDistMiNew_Pctiles <- group_by(TravDistMiNew_Ntile,
                                  PctR_Round_New
                                 ) %>% 
  summarise(
    MinTDMiAtPctile_N = min(TravelDistance_Mi_New),
    MinTDMiAtPctile_H = min(TravelDistance_Mi_NewHvrs),
    CntsAtPctile_N = sum(!is.na(TravelDistance_Mi_New)),
    CntsAtPctile_H = sum(!is.na(TravelDistance_Mi_NewHvrs)),
    PctsAtPctile_N = CntsAtPctile_N / TravDistMiNew_Ntile_Rows,
    PctsAtPctile_H = CntsAtPctile_H / TravDistMiNew_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP_N = cumsum(PctsAtPctile_N),
         CumSumPAtP_H = cumsum(PctsAtPctile_H)
        )
Error in eval(expr, envir, enclos) : 
  unknown variable to group by : PctR_Round_New

Investigation of TravelDistance_Mi_New.

Why are there still some small or zero TravelDistance_Mi_New values.

Explore instances where TravelDistance_Mi is NA.


View(group_by(AllDays_NewOrder,
              StartStop_ID
             ) %>% 
       summarise(Cnts = sum(is.na(TravelTime_Sec)
                           )
                ) %>% 
       arrange(desc(Cnts)
              )
    )

View(filter(AllDays_NewOrder,
            StartStop_ID == "5004635--5004758"
           ) %>% 
       select(TravelTime_Sec,
              TT_Sec_SS_Mean,
              TT_Sec_SSHG_Mean,
              TT_Sec_SS_Med,
              TT_Sec_SSHG_Med,
              TT_Sec_SS_Cnt,
              TT_Sec_SSHG_Cnt
              )
    )

Investigation of TravelTime_Hr.

View(TravDistMi_Pctiles): 98% of TravelTime_Hr are between 7 seconds and 464 seconds (~8 minutes).


TravTimeHr_Ntile <- as.data.frame(AllDays_NewTravelDist$TravelTime_Hr) %>% 
  mutate(Pctile = ntile(AllDays_NewTravelDist$TravelTime_Hr, 100),
         MinR = min_rank(AllDays_NewTravelDist$TravelTime_Hr),
         PctR = percent_rank(AllDays_NewTravelDist$TravelTime_Hr),
         PctR_Round = round(PctR, 2)
        ) 

colnames(TravTimeHr_Ntile)[1] <- "TravelTime_Hr"
str(TravTimeHr_Ntile)

TravTimeHr_Ntile_Rows <- nrow(TravTimeHr_Ntile)

View(tail(TravTimeHr_Ntile, 500))


TravTimeHr_Pctiles <- group_by(TravTimeHr_Ntile,
                               PctR_Round
                              ) %>% 
  summarise(
    MinTravTimeHrAtPctile = min(TravelTime_Hr),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / TravTimeHr_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile),
         MinTravTimeSecAtPctile = MinTravTimeHrAtPctile * 3600
        )

View(TravTimeHr_Pctiles)

Investigation of TravelTime_Hr.

Histogram of TravelTime_Sec.


TravTime_Sec_HistDen <- ggplot(filter(AllDays_NewTravelDist,
                                      !is.na(TravelTime_Sec)
                                     ),
                               aes(x = TravelTime_Sec,
                                   y = ..density..
                                  )
                          ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  # stat_bin(binwidth = 5,
  #          geom = "text",
  #          size = 2.5,
  #          vjust = 1.5,
  #          aes(label = format(..count.., big.mark = ",")
  #             ),
  #         ) +
  coord_cartesian(xlim = c(0, 180), ylim = c(0, 0.02)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Time",
       x = "Travel Time (sec)",
       y = "Density"
      )

TravTime_Sec_HistDen

Investigation of TravelTime_Hr.

Looking at odd TravelTime_Sec values.


View(filter(AllDays_NewTravelDist,
            is.na(TravelTime_Sec) & 
              !is.na(Odometer_Distance_Lag1)
           )
    )


# examples of TravelTime_Sec values that are NA. These are NA because the Event_Time & Departure_Time readings are not accurate (i.e., the previous Departure_Time is BEFORE the current Event_Time).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 90809 & RowNum_OG <= 90829) | # 90819
                (RowNum_OG >= 90881 & RowNum_OG <= 90901) | # 90891
                (RowNum_OG >= 994813 & RowNum_OG <= 994833) | # 994823
                (RowNum_OG >= 2391342 & RowNum_OG <= 2391362) # 2391352
           )
    )


View(filter(AllDays_NewTravelDist,
            TravelTime_Sec == 0
           )
    )

# examples where TravelTime_Sec is zero (i.e., previous Departure_Time equals the current Event_Time).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 175725 & RowNum_OG <= 175745) | # 175735
                (RowNum_OG >= 401127 & RowNum_OG <= 401147) | # 401137
                (RowNum_OG >= 2446820 & RowNum_OG <= 2446840) | # 2446830
                (RowNum_OG >= 2545036 & RowNum_OG <= 2545056) # 2545046
           )
    )


View(filter(AllDays_NewTravelDist,
            TravelTime_Sec > 0 &
              TravelTime_Sec < 10
           ) %>% 
       arrange(desc(SpeedAvg_Mph)
              )
    )


# examples where TravelTime_Sec is unusually small (with TravelDistance_Mi values that are large).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 1042228 & RowNum_OG <= 1042248) | # 1042238
                (RowNum_OG >= 53816 & RowNum_OG <= 53836) | # 53826
                (RowNum_OG >= 360571 & RowNum_OG <= 360591) | # 360581
                (RowNum_OG >= 502271 & RowNum_OG <= 502291) # 502281 (can't explian the weird TravelTime_Sec calculation here - it's not even an integer!)
           )
    )

# still trying to explain 502281...on the day of this weirdness, the bus was only in circulation for 4-5 stops (~20 minutes) on that day (Oct 6)
View(filter(AllDays_NewTravelDist,
            Bus_ID == 2711
           )
    )


# exploring large values for TravelTime_Sec
View(filter(AllDays_NewTravelDist,
            TravelTime_Sec == 300
           ) %>% 
       arrange(desc(TravelTime_Sec),
               SpeedAvg_Mph2
              )
    )

# examples where TravelTime_Sec is unusually large (with TravelDistance_Mi values that are small, so SpeedAvg_Mph values are very small).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 2627459 & RowNum_OG <= 2627479) | # 2627469
                (RowNum_OG >= 2193344 & RowNum_OG <= 2193364) | # 2193354
                (RowNum_OG >= 1644123 & RowNum_OG <= 1644143) | # 1644133
                (RowNum_OG >= 869600 & RowNum_OG <= 869620) # 869610
           )
    )

Investigation of SpeedAvg_Mph2

View(Speed_Pctiles): 90% of SpeedAvg_Mph2 are between ~3mph and ~66mph.


Speed_Ntile <- as.data.frame(AllDays_NewTravelDist$SpeedAvg_Mph2) %>% 
  mutate(Pctile = ntile(AllDays_NewTravelDist$SpeedAvg_Mph2, 100),
         MinR = min_rank(AllDays_NewTravelDist$SpeedAvg_Mph2),
         PctR = percent_rank(AllDays_NewTravelDist$SpeedAvg_Mph2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(Speed_Ntile)[1] <- "SpeedAvg_Mph2"
str(Speed_Ntile)

Speed_Ntile_Rows <- nrow(Speed_Ntile)

View(tail(Speed_Ntile, 500))


Speed_Pctiles <- group_by(Speed_Ntile,
                          PctR_Round
                         ) %>% 
  summarise(
    MinSpeedAtPctile = min(SpeedAvg_Mph2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / Speed_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(Speed_Pctiles)

Investigation of SpeedAvg_Mph2.

Exploring the removal of outlier TravelTime_Sec and TravelDistance_Mi.


summary(select(AllDays_NewTravelDist,
               SpeedAvg_Mph,
               SpeedAvg_Mph2
              )
       )

summary(select(filter(AllDays_NewTravelDist,
                      TravelDistance_Mi > 0.0001893939 & # lowest non-zero percentile
                        TravelDistance_Mi < 1.0812500000 & # 99th percentile
                        TravelTime_Sec > 10.050000 & # 2nd percentile
                        TravelTime_Sec < 293.000000 # 98th percentile
                     ),
               SpeedAvg_Mph,
               SpeedAvg_Mph2
              )
       )

Investigation of SpeedAvg_Mph2.

Histogram of SpeedAvg_Mph2.


Speed_HistDen <- ggplot(filter(AllDays_NewTravelDist,
                               !is.na(SpeedAvg_Mph2)
                              ),
                        aes(x = SpeedAvg_Mph2,
                            y = ..density..
                           )
                       ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  stat_bin(binwidth = 5,
           geom = "text",
           size = 2.5,
           vjust = 1.5,
           aes(label = format(..count.., big.mark = ",")
              ),
          ) +
  # geom_text(aes(label = format(..count.., big.mark = ",")
  #              ),
  #           size = 3,
  #           nudge_y = (..count.. * 0.1)
  #          ) +
  coord_cartesian(xlim = c(0, 70), ylim = c(0, 0.04)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Speed",
       x = "Average Speed (mph)",
       y = "Density"
      )

Speed_HistDen

Investigation of SpeedAvg_Mph2.

Histogram of SpeedAvg_Mph2 after removing outlier TravelTime_Sec and TravelDistance_Mi.


View(TravDistMiNew_Pctiles)
View(TravTimeHr_Pctiles)

SpeedNoOutlier_HistDen <- ggplot(filter(AllDays_NewTravelDist,
                                        !is.na(SpeedAvg_Mph2) &
                                          TravelDistance_Mi_New > 0.077841005 & # 5th percentile
                                          # TravelDistance_Mi_New < 1.0812500000 & # 99th percentile
                                          TravelTime_Sec > 12.100000 # 4th percentile
                                          # TravelTime_Sec < 293.000000 # 98th percentile
                                       ),
                                 aes(x = SpeedAvg_Mph2,
                                     y = ..density..
                                    )
                                ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  stat_bin(binwidth = 5,
           geom = "text",
           size = 2.5,
           vjust = 1.5,
           aes(label = format(..count.., big.mark = ",")
              ),
          ) +
  # geom_text(aes(label = format(..count.., big.mark = ",")
  #              ),
  #           size = 3,
  #           nudge_y = (..count.. * 0.1)
  #          ) +
  coord_cartesian(xlim = c(0, 70), ylim = c(0, 0.04)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Speed",
       subtitle = "(removed low outliers of Travel Distance and Travel Time)",
       x = "Average Speed (mph)",
       y = "Density"
      )

SpeedNoOutlier_HistDen

Investigation of SpeedAvg_Mph2.

New dataset (NoOutliers_TravelDistNTime) when removing outlier low values of TravelDistance_Mi_New and TravelTime_Sec.


View(TravDistMiNew_Pctiles)
View(TravTimeHr_Pctiles)

NoOutliers_TravelDistNTime <- filter(AllDays_NewTravelDist,
                                     TravelDistance_Mi_New > .077841005 & # 5th percentile
                                       # TravelDistance_Mi_New < 1.0812500000 & # 99th percentile
                                       TravelTime_Sec > 12.100000 # 4th percentile
                                       # TravelTime_Sec < 293.000000 # 98th percentile
                                    )

nrow(AllDays_NewTravelDist) - nrow(NoOutliers_TravelDistNTime)

str(NoOutliers_TravelDistNTime)
summary(NoOutliers_TravelDistNTime)

Investigation of SppedAvg_Mph2.

View(Speed_NoOut_Pctiles): Aproximately 90% of SpeedAvg_Mph2 values are between ~4mph and ~56mph.


Speed_NoOut_Ntile <- as.data.frame(NoOutliers_TravelDistNTime$SpeedAvg_Mph2) %>% 
  mutate(Pctile = ntile(NoOutliers_TravelDistNTime$SpeedAvg_Mph2, 100),
         MinR = min_rank(NoOutliers_TravelDistNTime$SpeedAvg_Mph2),
         PctR = percent_rank(NoOutliers_TravelDistNTime$SpeedAvg_Mph2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(Speed_NoOut_Ntile)[1] <- "SpeedAvg_Mph2"
str(Speed_NoOut_Ntile)

Speed_NoOut_Ntile_Rows <- nrow(Speed_NoOut_Ntile)

View(tail(Speed_NoOut_Ntile, 500))


Speed_NoOut_Pctiles <- group_by(Speed_NoOut_Ntile,
                                PctR_Round
                               ) %>% 
  summarise(
    MinSpeedAtPctile = min(SpeedAvg_Mph2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / Speed_NoOut_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(Speed_NoOut_Pctiles)

Investigation of SppedAvg_Mph2.

Exloring odd/impossible values.


# Exploring when SpeedAvg_Mph2 is NA  --  does not occur at all
nrow(filter(NoOutliers_TravelDistNTime,
            is.na(SpeedAvg_Mph2)
           )
    )


# Exploring when SpeedAvg_Mph2 is zero  --  does not occur at all
nrow(filter(NoOutliers_TravelDistNTime,
            SpeedAvg_Mph2 == 0
           )
    )


# examples where SpeedAvg_Mph2 < 3.2848770
View(filter(AllDays_NewTravelDist,
            SpeedAvg_Mph2 > 0 &
              SpeedAvg_Mph2 < 3.2848770
           ) %>% 
       arrange(SpeedAvg_Mph2)
    )

# examples where SpeedAvg_Mph2 < 3.2848770
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 485338 & RowNum_OG <= 485358) | # 485348  --  Extreme travel time, Route Change
                (RowNum_OG >= 346952 & RowNum_OG <= 346972) | # 346962  -- Extreme travel time, Route Change 
                (RowNum_OG >= 70494 & RowNum_OG <= 70514) | # 70504  --  Extreme travel time, Route Change
                (RowNum_OG >= 2051846 & RowNum_OG <= 2051866) # 2051856  --  Extreme travel time, Route Change
           )
    )

Investigation of SpeedAvg_Mph2.

Limit the dataset based on SpeedAvg_Mph2.


NoOutliersSpeed <- filter(NoOutliers_TravelDistNTime,
                          between(SpeedAvg_Mph2,
                                  4.069300, # 5th percentile
                                  56.05651 #95th percentile
                                 )
                          )

nrow(NoOutliers_TravelDistNTime) - nrow(NoOutliersSpeed)

summary(NoOutliersSpeed)

TravelTime now looks like it has some odd values on the high end. So let’s look at those.

View(TravTime_NoOut_Pctiles): Virtually all trips should take less than 5 minutes. (The 99th percentile of of TravelTime is approximately 8 minutes.)


TravTime_NoOut_Ntile <- as.data.frame(NoOutliersSpeed$TravelTime_Hr) %>% 
  mutate(Pctile = ntile(NoOutliersSpeed$TravelTime_Hr, 100),
         MinR = min_rank(NoOutliersSpeed$TravelTime_Hr),
         PctR = percent_rank(NoOutliersSpeed$TravelTime_Hr),
         PctR_Round = round(PctR, 2)
        )

colnames(TravTime_NoOut_Ntile)[1] <- "TravelTime_Hr"
str(TravTime_NoOut_Ntile)

TravTime_NoOut_Ntile_Rows <- nrow(TravTime_NoOut_Ntile)

View(tail(TravTime_NoOut_Ntile, 500))


TravTime_NoOut_Pctiles <- group_by(TravTime_NoOut_Ntile,
                                   PctR_Round
                                  ) %>% 
  summarise(
    MinTravTimeHrAtPctile = min(TravelTime_Hr),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / TravTime_NoOut_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile),
         MinTravTimeSecAtPctile = MinTravTimeHrAtPctile * (60 * 60)
        )

View(TravTime_NoOut_Pctiles)

Investigating odd TravelTime_Sec values.

Trips longer than ~8 minutes.


View(filter(NoOutliersSpeed,
            TravelTime_Sec > 491 # min at the 100th percentile
           ) %>% 
       arrange(desc(TravelTime_Sec)
              )
    )

# examples of TravelTime_Sec values that are largest.
View(filter(NoOutliersSpeed,
            (RowNum_OG >= 2071759 & RowNum_OG <= 2071779) | # 2071769  --  results from a route change, and a 3hr+ wait before the new route starts
                (RowNum_OG >= 1473686 & RowNum_OG <= 1473706) | # 1473696  --  results from a route change, and a 3hr wait before the new route starts
                (RowNum_OG >= 1222822 & RowNum_OG <= 1222842) | # 1222832  --  results from a route change, and a 3hr wait before the new route starts
                (RowNum_OG >= 3046089 & RowNum_OG <= 3046109) # 3046099  --  results from a route change, and a 3hr wait before the new route starts
           )
    )


# examples of TravelTime_Sec values that are the smallest of the large.
View(filter(NoOutliersSpeed,
            (RowNum_OG >= 3044689 & RowNum_OG <= 3044709) | # 3044699  --  results from a route change
                (RowNum_OG >= 3022358 & RowNum_OG <= 3022378) | # 3022368  --  results from a route change
                (RowNum_OG >= 2993016 & RowNum_OG <= 2993036) | # 2993026  --  results from a previous route change (change occurred in deleted row)
                (RowNum_OG >= 2683703 & RowNum_OG <= 2683723) # 2683713  --  results from a previous route change (change occurred in deleted row)
           )
    )

Let’s look at the TravelTime_Sec values and route changes (DirChange2).

The 99th percentile of TravelTime_Sec for both, all trips, and just those trips NOT involving route changes (DirChange2 = “Same”), is approximately 5min (300 sec).

Nota Bene: The percentile calculation here is defined slightly different than in most of the above analyses (which get the lowest value in the bin created by 100 ntiles).


summary(select(NoOutliersSpeed,
               TravelTime_Sec
              )
       )

summary(select(filter(NoOutliersSpeed,
                      DirChange2 == "Same"
                     ),
               TravelTime_Sec
              )
       )

summary(select(filter(NoOutliersSpeed,
                      DirChange2 == "Change"
                     ),
               TravelTime_Sec
              )
       )


TravTimeSec_Qtiles_df <- data.frame(PctValue = seq(0, 100, 1),
                                    All = seq(1, 101, 1),
                                    Same = seq(1, 101, 1),
                                    Change = seq(1, 101, 1)
                                   )

TravTimeSec_Qtiles_df[ , 2] <- quantile(select(NoOutliersSpeed,
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

TravTimeSec_Qtiles_df[ , 3] <- quantile(select(filter(NoOutliersSpeed,
                                                      DirChange2 == "Same"
                                                     ),
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

TravTimeSec_Qtiles_df[ , 4] <- quantile(select(filter(NoOutliersSpeed,
                                                      DirChange2 == "Change"
                                                     ),
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

View(TravTimeSec_Qtiles_df)

Limit the dataset now based on TravelTime_Sec.


UpperLimitTravTime <- filter(NoOutliersSpeed,
                             TravelTime_Sec <= 491 # min at the 100th percentile
                             )

nrow(NoOutliersSpeed) - nrow(UpperLimitTravTime)

str(UpperLimitTravTime)

summary(UpperLimitTravTime)

Investigation of Dwell_Time2 (how long the bus is at a stop).

Differences between Dwell_Time (by WMATA) and Dwell_Time2 (by me) appear to be due to switches in RouteAlt. WMATA calculates Dwell_Time by an unknown process. The WMATA calculation is equal to my calculation, except for the records immedaitely before and after a RouteAlt switch (DirChange2).


View(filter(AllDays_NewOrder,
            Dwell_Time != Dwell_Time2
           )
    )


# Examples where the Dwell_Time and Dwell_Time2 are different
View(filter(AllDays_NewOrder,
            ( (RowNum_OG >= 65 & RowNum_OG <= 85) | # 75
                (RowNum_OG >= 162 & RowNum_OG <= 192) | # 172
                (RowNum_OG >= 431952 & RowNum_OG <= 431972) | # 431962
                (RowNum_OG >= 434595 & RowNum_OG <= 434615) # 434605  --  this record is NOT a route switch, but does has a Sequence switch (Me: should there really be a route switch here?)
            )
           )
    )

Investigation of Dwell_Time2 (how long the bus is at a stop).

First, create some “rank” stats. View(DT2_Pctiles): 95% of Dwell_Time2s are <= 23 seconds…but some weird (e.g., nearly 2 hour Dwell_Time2s exist).


DwellTime2_Ntile <- as.data.frame(AllDays_NewOrder$Dwell_Time2) %>% 
  mutate(Pctile = ntile(AllDays_NewOrder$Dwell_Time2, 100),
         MinR = min_rank(AllDays_NewOrder$Dwell_Time2),
         PctR = percent_rank(AllDays_NewOrder$Dwell_Time2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DwellTime2_Ntile)[1] <- "Dwell_Time2"
str(DwellTime2_Ntile)

DwellTime2_Ntile_Rows <- nrow(DwellTime2_Ntile)

View(tail(DwellTime2_Ntile, 500))


DwellTime2_Pctiles <- group_by(DwellTime2_Ntile,
                               PctR_Round
                              ) %>% 
  summarise(
    MinDwellAtPctile = min(Dwell_Time2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DwellTime2_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DwellTime2_Pctiles)

Investigation of Dwell_Time2 (how long the bus is at a stop).

Histogram of Dwell_Time2.


DwellTime2_HistDen <- ggplot(AllDays_NewOrder, aes(x = Dwell_Time2, y = ..density..)) +
  geom_histogram(binwidth = 1, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(1, 25), ylim = c(0, 0.05)
                 ) +
  xlab("Time a Bus Stays at a Stop (sec)") + 
  ylab("Density") + 
  #  theme(legend.position="none") + 
  ggtitle(expression(atop("Variation in How Long a Bus Stays at a Stop"
                          # ,atop(italic("xxxxx"),"")
                         )
                    )
         )

DwellTime2_HistDen

Investigation of Dwell_Time2 (how long the bus is at a stop).

Looking at some weirdly long Dwell_Time2 values.


View(arrange(AllDays_NewOrder,
             desc(Dwell_Time2)
            )
    )


# examples of extremely large Dwell_Time2s
View(filter(AllDays_NewOrder,
            (RowNum_OG >= 292669 & RowNum_OG <= 292689) | # 292679
                (RowNum_OG >= 531057 & RowNum_OG <= 531077) | # 531067
                (RowNum_OG >= 1388627 & RowNum_OG <= 1388647) | # 1388637
                (RowNum_OG >= 1645711 & RowNum_OG <= 1645731) # 1645721
           )
    )


View(filter(AllDays_NewOrder,
            Dwell_Time2 == 0
           )
    )

Investigation of Delta_Time (how early or late the bus is).

View(DT2_Pctiles): 94% of Delta_Time values are between -236 seconds and 1,259 seconds. Roughly 66% of records are within 5 min late and 5 min early…but some weird (e.g., almost 50 minute late or 40 minute early) Delta_Times exist.

Note that Delta_Time is the difference from the scheduled bus arrival. So if two buses are scheduled to arrive at a destination at 10:00pm and 10:20pm, and if the 10:20pm bus has a Delta_Time of 5 minutes, there are 25 minutes between bus arrivals at the stop.

Also note that based on a comment at https://planitmetro.com/2016/11/16/data-download-metrobus-vehicle-location-data/, the Delta_Time values don’t appear to coincide with published bus schedules (e.g., the X2 departing every 8 minutes during peak hours).


DeltTime_Ntile <- as.data.frame(AllDays_NewOrder$Delta_Time) %>% 
  mutate(Pctile = ntile(AllDays_NewOrder$Delta_Time, 100),
         MinR = min_rank(AllDays_NewOrder$Delta_Time),
         PctR = percent_rank(AllDays_NewOrder$Delta_Time),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DeltTime_Ntile)[1] <- "Delta_Time"
str(DeltTime_Ntile)

DeltTime_Ntile_Rows <- nrow(DeltTime_Ntile)

View(tail(DeltTime_Ntile, 500))


DeltTime_Pctiles <- group_by(DeltTime_Ntile,
                             PctR_Round
                            ) %>% 
  summarise(
    MinDeltTimeAtPctile = min(Delta_Time),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DeltTime_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DeltTime_Pctiles)
DeltTime_Pctiles

# ~66% of rows are between 5 min late and 5 min early
nrow(filter(AllDays_NewOrder,
            Delta_Time >= -300 &
              Delta_Time <= 300
           )
    ) / nrow(AllDays_NewOrder)


# examples of weird large Delta_Times
View(filter(AllDays_NewOrder,
            Delta_Time < -4202 |
              Delta_Time > 1705
           ) %>% 
       arrange(desc(Delta_Time)
              )
    )

Investigation of Delta_Time (how early or late the bus is).

Delta_Time histogram.


DeltTime_HistDen <- ggplot(AllDays_NewOrder, aes(x = (Delta_Time / 60),
                                                 y = ..density..
                                                )
                          ) +
  geom_histogram(binwidth = (5/60), fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(-5, 5)) +
  xlab("Bus Lateness (min)") + 
  ylab("Density") + 
  #  theme(legend.position="none") + 
  ggtitle(expression(atop("Variation in How Early/Late a Bus Is",
                          atop(italic("(positive values are late arrivals)"),
                               ""
                              )
                         )
                    )
         )

DeltTime_HistDen

Investigation of Delta_Time (how early or late the bus is).

Delta_Time boxplot.


# Count_Values is needed to display the medians on the box plots
Count_Values <- ddply(AllDays_NewOrder,
                      .(Event_Time_HrGroup),
                      summarise,
                      Value_Counts = median(Delta_Time / 60, na.rm = TRUE)
                     )

DeltTime_BoxPlot <- ggplot(AllDays_NewOrder,
                           aes(factor(Event_Time_HrGroup),
                               Delta_Time / 60,
                               fill = factor(Event_Time_HrGroup)
                              )
                          ) + 
  geom_boxplot(outlier.colour="red", notch=TRUE) + 
  # coord_cartesian(ylim = c(-300, 1200)) +
  coord_cartesian(ylim = c(-5, 20)) +
  geom_text(data = Count_Values,
            aes(y = Value_Counts,
                label = format(round(Value_Counts, digits = 1),
                               nsmall = 1
                              )
               ),
            size = 3,
            vjust = -0.5
           ) +
  xlab("Hour Group") + 
  ylab("Bus Lateness (minutes)") + 
  theme(legend.position="none", axis.text.x = element_text(angle=45)) + 
  #theme(legend.position="right", axis.text.x = element_blank()) + 
  ggtitle(expression(atop("How Early/Late is the Bus (by Hour Group)",
                          atop(italic("(positive values are late arrivals)"),
                               ""
                              )
                         )
                    )
         )

DeltTime_BoxPlot

Investigation of Delta_Time (how early or late the bus is).

Exploring “extreme” Delta_Times. First let’s get some “rank” stats.


View(DeltTime_Pctiles)
DeltTime_Pctiles


DeltTimeAbs_Ntile <- as.data.frame(abs(AllDays_NewOrder$Delta_Time)) %>% 
  mutate(Pctile = ntile(abs(AllDays_NewOrder$Delta_Time), 100),
         MinR = min_rank(abs(AllDays_NewOrder$Delta_Time)),
         PctR = percent_rank(abs(AllDays_NewOrder$Delta_Time)),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DeltTimeAbs_Ntile)[1] <- "Delta_Time_Abs"
str(DeltTimeAbs_Ntile)

DeltTimeAbs_Ntile_Rows <- nrow(DeltTimeAbs_Ntile)

View(tail(DeltTimeAbs_Ntile, 500))


DeltTimeAbs_Pctiles <- group_by(DeltTimeAbs_Ntile,
                                PctR_Round
                               ) %>% 
  summarise(
    MinDeltTimeAtPctile = min(Delta_Time_Abs),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DeltTime_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DeltTimeAbs_Pctiles)
DeltTimeAbs_Pctiles

Investigation of Delta_Time (how early or late the bus is).

Exploring “extreme” Delta_Times. Then let’s calculate the percentage of buses that are 10 minutes (or more) late/early.


HrGroup_DeltaTime_All <- group_by(AllDays_NewOrder,
                                  Event_Time_HrGroup
                                 ) %>% 
  summarise(EventAll_Cnt = n()
           )

str(HrGroup_DeltaTime_All)
View(HrGroup_DeltaTime_All)


HrGroup_DeltaTime_Above10Min <- filter(AllDays_NewOrder,
                                       abs(Delta_Time) >= 600
                                      ) %>% 
  group_by(Event_Time_HrGroup) %>% 
  summarise(EventAbove10_Cnt = n()
           )

str(HrGroup_DeltaTime_Above10Min)
View(HrGroup_DeltaTime_Above10Min)


HrGroup_DeltaTimeCompare <- inner_join(HrGroup_DeltaTime_Above10Min,
                                       HrGroup_DeltaTime_All,
                                       by = c("Event_Time_HrGroup" = "Event_Time_HrGroup")
                                      ) %>% 
  mutate(PctEventsAbove10 = EventAbove10_Cnt / EventAll_Cnt)

View(HrGroup_DeltaTimeCompare)

Investigation of Delta_Time (how early or late the bus is).

Quickly plot these “extreme” Delta_Times.


DeltTime_Above10_Cols <- ggplot(HrGroup_DeltaTimeCompare,
                                aes(factor(Event_Time_HrGroup),
                                    PctEventsAbove10
                                   )
                               ) +
  geom_col(fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_text(aes(label = format(round(PctEventsAbove10, digits = 2),
                               nsmall = 2
                              )
               ),
            size = 3,
            nudge_y = (HrGroup_DeltaTimeCompare$PctEventsAbove10 * -0.1)
           ) +
  # coord_cartesian(xlim = c(-5, 5)) +
  xlab("Hour Group") + 
  ylab("Percent of All Bus Arrivals") +
  theme(legend.position="none", axis.text.x = element_text(angle=45)) +
  ggtitle(expression(atop("When is a Bus 10+ Minutes Late/Early"
                          # ,atop(italic("positive values are late arrivals"),
                          #      ""
                          #     )
                         )
                    )
         )

DeltTime_Above10_Cols

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Correlation.


DwellTDeltaT_Corr <- as.matrix(cor(x = AllDays_NewOrder$Dwell_Time2,
                                   y = AllDays_NewOrder$Delta_Time,
                                   use = "pairwise"
                                  )
                               )

DwellTDeltaT_Corr

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Next, let’s get a sample of data for plotting. Let’s do this for the full dataset (AllDays_NewOrder).


AllDays_NewOrder_10PctSamp <- sample_frac(AllDays_NewOrder, 0.1) %>% 
  select(Delta_Time,
         Dwell_Time2
        ) %>% 
  mutate(DataSet = "AllData")

str(AllDays_NewOrder_10PctSamp)

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Let’s also get a sample of data for plotting, but with a datset that removes outliers.


View(DeltTime_Pctiles)
View(DwellTime2_Pctiles)

AllDays_NewOrder_NoExtremes_10PctSamp <- filter(AllDays_NewOrder,
                                                between(Delta_Time, -402, 1705) & # removes about 2% of Delta_Time values
                                                  between(Dwell_Time2, 1, 63)  # removes about 2% of Dwell_Time2 values
                                               ) %>% 
  sample_frac(0.1) %>% 
  select(Delta_Time,
         Dwell_Time2
        ) %>% 
  mutate(DataSet = "OutliersRemoved")

str(AllDays_NewOrder_NoExtremes_10PctSamp)

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from the dataset that does not remove outliers.


DwellTDeltaT_Scatter <- ggplot(AllDays_NewOrder_10PctSamp,
                               aes(Dwell_Time2, Delta_Time)
                              ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  geom_smooth(method = "lm", colour = "red") +
  # xlab("Time at Stop (sec)") + 
  # ylab("Lateness (sec)") +
  annotate(label = lm_eqn(df = AllDays_NewOrder_10PctSamp,
                          y = AllDays_NewOrder_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_10PctSamp$Dwell_Time2
                         ),
           x = 2200,
           y = 600,
           geom = "text",
           size = 3,
           colour = "red",
           parse = TRUE
          ) +
  labs(title = "Lateness vs Time at Stop",
       subtitle = "(no outliers removed)",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
  #                         ,atop(italic("(no outliers removed)"),
  #                               ""
  #                              )
  #                        )
  #                   )
  #        )
# +
#   geom_jitter()

DwellTDeltaT_Scatter

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from the dataset that does remove outliers.


DwellTDeltaT_Scatter_NoExtremes <- ggplot(AllDays_NewOrder_NoExtremes_10PctSamp,
                                          aes(Dwell_Time2, Delta_Time)
                                         ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  geom_smooth(method = "lm", colour = "blue") +
  # xlab("Time at Stop (sec)") + 
  # ylab("Lateness (sec)") +
  annotate(label = lm_eqn(df = AllDays_NewOrder_NoExtremes_10PctSamp,
                          y = AllDays_NewOrder_NoExtremes_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_NoExtremes_10PctSamp$Dwell_Time2
                         ),
           x = 50,
           y = -475,
           geom = "text",
           size = 3,
           colour = "blue",
           parse = TRUE
          ) +
  labs(title = "Lateness vs Time at Stop",
       subtitle = "(2% of outliers removed)",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
  #                         ,atop(italic("(2% of outliers removed)"),
  #                               ""
  #                              )
  #                        )
  #                   )
  #        )
# +
#   geom_jitter()

DwellTDeltaT_Scatter_NoExtremes

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from both datasets together.


CombinedData <- rbind(AllDays_NewOrder_10PctSamp,
                      AllDays_NewOrder_NoExtremes_10PctSamp
                     )

CombinedData$DataSet <- factor(CombinedData$DataSet)

str(CombinedData)


DwellTDeltaT_Scatter_Combined <- ggplot(CombinedData,
                                        aes(x = Dwell_Time2,
                                            y = Delta_Time,
                                            colour = DataSet
                                           )
                                       ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  coord_cartesian(xlim = c(0, 500), ylim = c(-1000, 2000)
                 ) +
  geom_smooth(data = filter(CombinedData,
                            DataSet == "AllData"
                           ),
              method = "lm",
              colour = "red"
             ) +
  geom_smooth(data = filter(CombinedData,
                            DataSet == "OutliersRemoved"
                           ),
              method = "lm",
              colour = "blue"
             ) +
  # facet_wrap( ~ DataSet, ncol = 2) +
  annotate(label = lm_eqn(df = AllDays_NewOrder_10PctSamp,
                          y = AllDays_NewOrder_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_10PctSamp$Dwell_Time2
                         ),
           x = 300,
           y = -600,
           geom = "text",
           size = 3,
           colour = "red",
           parse = TRUE
          ) +
  annotate(label = lm_eqn(df = AllDays_NewOrder_NoExtremes_10PctSamp,
                          y = AllDays_NewOrder_NoExtremes_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_NoExtremes_10PctSamp$Dwell_Time2
                         ),
           x = 300,
           y = -800,
           geom = "text",
           size = 3,
           colour = "blue",
           parse = TRUE
          ) +
  theme(legend.position = "bottom") +
  labs(title = "Lateness vs Time at Stop",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
                          # ,atop(italic("2% of outliers removed"),
                          #       ""
                          #      )
         #                 )
         #            )
         # )
# +
#   geom_jitter()

DwellTDeltaT_Scatter_Combined

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayBmb3IgV01BVEEgTWV0cm9idXMgRGF0YSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2sgZm9yIGFuYWx5c2lzIHVzaW5nIGRhdGEgb24gdGhlIERDIEJ1cyBTeXN0ZW0gKFdNQVRBIE1ldHJvYnVzKS4gIFRoZSBkYXRhIHdlcmUgb2J0YWluZWQgaGVyZToKCmh0dHBzOi8vcGxhbml0bWV0cm8uY29tLzIwMTYvMTEvMTYvZGF0YS1kb3dubG9hZC1tZXRyb2J1cy12ZWhpY2xlLWxvY2F0aW9uLWRhdGEvCgpDb250cm9sICsgQWx0ICsgU2hpZnQgKyBtID0gcmVuYW1lIGluIHNjb3BlCgpMb2FkIHRoZSBwYWNrYWdlcyB0byBiZSB1c2VkLgpgYGB7ciBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KCmxpYnJhcnkoInRpZHlyIikKbGlicmFyeSgicGx5ciIpCmxpYnJhcnkoImRwbHlyIikKbGlicmFyeSgibWFncml0dHIiKQpsaWJyYXJ5KCJzdHJpbmdyIikKbGlicmFyeSgiZGF0YS50YWJsZSIpCmxpYnJhcnkoImx1YnJpZGF0ZSIpCmxpYnJhcnkoImdlb3NwaGVyZSIpCmxpYnJhcnkoImdncGxvdDIiKQpsaWJyYXJ5KCJnZ3ZpcyIpCmxpYnJhcnkoInJib2tlaCIpCgpgYGAKCgpHZXQgdGhlIGRhdGEuCgpGaXJzdCBsZXQncyBjaGVjayB0aGUgd29ya2luZyBkaXJlY3RvcnkuCmBgYHtyfQoKZ2V0d2QoKQoKYGBgCgoKVGhlbiwgYWN0dWFsbHkgZ2V0IHRoZSBkYXRhLgpgYGB7ciBlY2hvID0gRkFMU0V9CgpzZXR3ZCgiL1VzZXJzL21kdHVyc2UvRGVza3RvcC9BbmFseXRpY3MvRENNZXRyb0J1cy9CdXMgQVZMIE9jdCAyMDE2IikKCmZvciAoaSBpbiAzOjcpewogIGFzc2lnbihwYXN0ZTAoIk9jdDAiLCBpLCAiUmF3IiksCiAgICAgICAgIHJlYWQuZGVsaW0ocGFzdGUwKCIyMDE2MTAwIiwgaSwgIk1ldHJvYnVzQVZMLnR4dCIpLAogICAgICAgICAgICAgICAgICAgIHNlcCA9ICJcdCIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICBuYS5zdHJpbmdzID0gTlVMTAogICAgICAgICAgICAgICAgICAgKQogICAgICAgICkKICAKICBtZXNzYWdlKCJPY3QwIiwgaSwgIlJhdyIpCiAKICBzdHIoZ2V0KHBhc3RlMCgiT2N0MCIsIGksICJSYXciKQogICAgICAgICApCiAgICAgKQogIH0KCmBgYAoKClB1dCB0aGUgZGFpbHkgZGF0YSB0b2dldGhlci4KYGBge3J9CgpBbGxEYXlzIDwtIGJpbmRfcm93cyhsaXN0KE9jdDAzUmF3LCBPY3QwNFJhdywgT2N0MDVSYXcsIE9jdDA2UmF3LCBPY3QwN1JhdyksCiAgICAgICAgICAgICAgICAgICAgIC5pZCA9IGMoImdyb3VwIikKICAgICAgICAgICAgICAgICAgICApCiMgZGltKEFsbERheXMpCnN0cihBbGxEYXlzKQoKYGBgCgoKRGVsZXRpbmcgb2xkIGRhdGEgZnJhbWVzLgpgYGB7cn0KCmZvciAoaSBpbiAzOjcpewogIHJtKGxpc3QgPSBscyhwYXR0ZXJuID0gcGFzdGUwKCJPY3QwIiwgaSwgIlJhdyIpCiAgICAgICAgICAgICAgKQogICAgKQogIAogIG1lc3NhZ2UoIkRlbGV0aW5nIE9jdDAiLCBpLCAiUmF3IikKICB9CgpgYGAKCgpVcGRhdGluZyB2YXJpYWJsZSB0eXBlcy4KClRoZW4sIHNvcnRpbmcgdGhlIGRhdGEgYW5kIGFkZGluZyBhIFJvd051bWJlciAodG8gYmUgdXNlZCBmb3IgaWRlbnRpZnlpbmcgcm93cyBsYXRlciBpbiB0aGUgYW5hbHlzZXMuKQpgYGB7cn0KCkFsbERheXMkZ3JvdXAgPC0gZmFjdG9yKEFsbERheXMkZ3JvdXApCkFsbERheXMkUm91dGVfRGlyZWN0aW9uIDwtIGZhY3RvcihBbGxEYXlzJFJvdXRlX0RpcmVjdGlvbikKQWxsRGF5cyRFdmVudF9UaW1lIDwtIGFzLlBPU0lYY3QoQWxsRGF5cyRFdmVudF9UaW1lLCBmb3JtYXQgPSAiJW0tJWQtJXkgJUk6JU06JVMgJXAiKQpBbGxEYXlzJERlcGFydHVyZV9UaW1lIDwtIGFzLlBPU0lYY3QoQWxsRGF5cyREZXBhcnR1cmVfVGltZSwgZm9ybWF0ID0gIiVtLSVkLSV5ICVJOiVNOiVTICVwIikKCnN0cihBbGxEYXlzKQoKCkFsbERheXNfU29ydGVkIDwtIGFycmFuZ2UoQWxsRGF5cywKICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZQogICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFJvd051bV9PRyA9IHJvd19udW1iZXIoKSAjIHRoaXMgaXMgdXNlZnVsIGluIGlkZW50aWZ5IHRoZSByb3cgbGF0ZXIgb24KICAgICAgICApCgpybShBbGxEYXlzKQpzdHIoQWxsRGF5c19Tb3J0ZWQpCgojIFZpZXcoaGVhZChBbGxEYXlzX1NvcnRlZCwgMTAwKSkKCmBgYAoKCkluc3BlY3RpbmcgdGhlIHZhbHVlcyBvZiBTdG9wX0lELCBhbmQgZmluZGluZyB0aGF0IGl0IGNhbiB0YWtlIHRoZSB2YWx1ZXMgIiIgKGJsYW5rKSBhbmQgIk5VTEwiLgpgYGB7cn0KClZpZXcoZ3JvdXBfYnkoQWxsRGF5c19Tb3J0ZWQsCiAgICAgICAgICAgICAgU3RvcF9JRAogICAgICAgICAgICAgKSAlPiUgCiAgICAgICBzdW1tYXJpc2UoCiAgICAgICAgIENudCA9IG4oKQogICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoU3RvcF9JRCkKICAgICkKClZpZXcoZmlsdGVyKEFsbERheXNfU29ydGVkLAogICAgICAgICAgICBpcy5uYShTdG9wX0lEKSB8CiAgICAgICAgICAgICAgU3RvcF9JRCA9PSAiIiB8CiAgICAgICAgICAgICAgU3RvcF9JRCA9PSAiTlVMTCIKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoU3RvcF9EZXNjKQogICAgKQoKYGBgCgoKQ3JlYXRpbmcgYSB0YWJsZSBvZiBkaXN0aW5jdCBTdG9wX0Rlc2MgdmFsdWVzIHdoZW4gU3RvcF9JRCBpcyAiIiAoYmxhbmspIG9yICJOVUxMIi4KYGBge3J9CgpTdG9wSURfTmV3IDwtIGZpbHRlcihBbGxEYXlzX1NvcnRlZCwKICAgICAgICAgICAgICAgICAgICAgaXMubmEoU3RvcF9JRCkgfAogICAgICAgICAgICAgICAgICAgICAgIFN0b3BfSUQgPT0gIiIgfAogICAgICAgICAgICAgICAgICAgICAgIFN0b3BfSUQgPT0gIk5VTEwiCiAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc2VsZWN0KFN0b3BfSUQsIFN0b3BfRGVzYykgJT4lIAogIGRpc3RpbmN0KCkgJT4lIAogIGFycmFuZ2UoU3RvcF9JRCwgU3RvcF9EZXNjKSAlPiUgCiAgbXV0YXRlKFN0b3BJRF9OZXcgPSAxOm5yb3coLikKICAgICAgICApCgpWaWV3KFN0b3BJRF9OZXcpCgpgYGAKCgpDcmVhdGluZyBhIGZ1bGwgdXBkYXRlZCB0YWJsZSBieSBmaWxsaW5nIGluIFN0b3BJRF9OZXcgZm9yIHdoZW4gU3RvcF9JRCBpcyAiIiAoYmxhbmspIG9yIE5VTEwuCmBgYHtyfQoKQWxsRGF5c19TdG9wSUROZXcgPC0gbGVmdF9qb2luKEFsbERheXNfU29ydGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0KFN0b3BJRF9OZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9EZXNjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0b3BJRF9OZXcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIlN0b3BfRGVzYyIgPSAiU3RvcF9EZXNjIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFN0b3BJRF9DbGVhbiA9IGlmZWxzZShpcy5uYShTdG9wSURfTmV3KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdG9wSURfTmV3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFN0b3BJRF9JbmRpY2F0b3IgPSBmYWN0b3IoaWZlbHNlKGlzLm5hKFN0b3BJRF9OZXcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSURfT0siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSURfQmFkIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICApCgpybShTdG9wSURfTmV3KQpybShBbGxEYXlzX1NvcnRlZCkKc3RyKEFsbERheXNfU3RvcElETmV3KQoKIyBWaWV3KHRhaWwoQWxsRGF5c19TdG9wSUROZXcsIDUwMCkpCiMgVmlldyhmaWx0ZXIoQWxsRGF5c19TdG9wSUROZXcsCiMgICAgICAgICAgICAgU3RvcF9EZXNjID09ICJNRVRST1dBWSBBTk5OT1VDRU1OVCBDT1JSIgojICAgICAgICAgICAgKQojICAgICApCgpgYGAKCgpGZWF0dXJlIGVuZ2luZWVyaW5nLgoKSW5zcGVjdGluZyBpbmNpZGVuY2VzIG9mIGNvbnNlY3V0aXZlIFN0b3BfSURzLiBUaGlzIGlzIGRvbmUgYmVjYXVzZSBpbnZlc3RpZ2F0aW9uIHNob3dlZCB0aGF0IG1hbnkgY29uc2V1dGl2ZSBldmVudHMgb2NjdXJyIGF0IHRoZSBzYW1lIFN0b3BfSUQsIGJ1dCB3aXRoIHZhcmlvdXMgRHdlbGxfVGltZXMsIE9kb21ldGVyX0Rpc3RhbmNlcywgZXRjLiAgQWxsIG9mIHdoaWNoIGFmZmVjdCBjYWxjdWxhdGlvbnMgYW5kIGFuYWx5c2VzLgoKQ3JlYXRlIGRhdGEgb24gdGhlIHJ1bnMgKGNvbnNlY3V0aXZlIFN0b3BfSURzKS4KYGBge3J9CgpTdG9wSURfUnVucyA8LSBybGUoQWxsRGF5c19TdG9wSUROZXckU3RvcElEX0NsZWFuKQoKU3RvcElEX1J1bnMkZW5kcyA8LSBjdW1zdW0oU3RvcElEX1J1bnMkbGVuZ3RocykKClN0b3BJRF9SdW5zJHN0YXJ0cyA8LSBpZmVsc2UoaXMubmEobGFnKFN0b3BJRF9SdW5zJGVuZHMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFnKFN0b3BJRF9SdW5zJGVuZHMpICsgMQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKc3RyKFN0b3BJRF9SdW5zKQojIGNsYXNzKFN0b3BJRF9SdW5zKQojIAojIFN0b3BJRF9SdW5zX2RmIDwtIGRhdGEuZnJhbWUodW5jbGFzcyhTdG9wSURfUnVucykpCiMgc3RyKFN0b3BJRF9SdW5zX2RmKQojIGNsYXNzKFN0b3BJRF9SdW5zX2RmKQojIHJtKFN0b3BJRF9SdW5zX2RmKQoKYGBgCgoKVHJ5aW5nIHRvIGxpbmsgZGF0YSBvbiBSdW5zR3JvdXBzIHdpdGggdGhlIG9yaWdpbmFsIGRhdGEgKEFsbERheXNfU29ydGVkKS4gVGhlIGdvYWwgaXMgdG8gc2VsZWN0IG9ubHkgb25lIHJlY29yZCBwZXIgUnVuc0dyb3VwIC0gdGhhdCBiZWluZyB0aGUgcmVjb3JkIHdpdGggdGhlIGxvbmdlc3QgRHdlbGxfVGltZS4KCkkgYXR0ZW1wdGVkIHRoaXMgY29tcHV0YXRpb24gdXNpbmcgYm90aCBkYXRhLmZyYW1lcyAoZHBseXIpIGFuZCBkYXRhLnRhYmxlcyAoZGF0YS50YWJsZSkuIEhvd2V2ZXIsIHdpdGggMiw4MDksMDYyIHJvd3MgaW4gb25lIGRhdGFzZXQgYW5kIDMsMTE5LDQ0MyByb3dzIGluIHRoZSBvdGhlciBkYXRhc2V0LCB0aGUgY3VycmVudCBjb21wdXRhdGlvbiB0aW1lIGlzIG92ZXIgNSBkYXlzLi4uc28gSSdtIHRyeWluZyBhIGRpZmZlcmVudCBzdHJhdGVneSB0byBvbmx5IHNlbGVjdCB0aGUgZmlyc3QgcmVjb3JkIGluIGEgcnVuLgpgYGB7cn0KCiMgQ3JlYXRlIGEgUnVuc0dyb3VwIHZhcmlhYmxlIGZvciBlYWNoIHJ1bgojIFN0b3BJRF9SdW5zX2RmJFJ1bnNHcm91cCA8LSBwYXN0ZTAoImciLCBzZXEoMTpucm93KFN0b3BJRF9SdW5zX2RmKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAKIyBzdHIoU3RvcElEX1J1bnNfZGYpCiMgaGVhZChTdG9wSURfUnVuc19kZiwgMjUpCiMgdGFpbChTdG9wSURfUnVuc19kZiwgMjUpCiMgCiMgU3RvcElEX1J1bnNfZGYgPC0gU3RvcElEX1J1bnNfZGYgJT4lIAojICAgbXV0YXRlKFJvd051bSA9IHJvd19udW1iZXIoKQojICAgICAgICAgKQojIAojIHN0cihTdG9wSURfUnVuc19kZikKIyBoZWFkKFN0b3BJRF9SdW5zX2RmLCAyNSkKIyB0YWlsKFN0b3BJRF9SdW5zX2RmLCAyNSkKIyAKIyAKIyAjIENvbnZlcnRpbmcgdG8gZGF0YS50YWJsZXMgZm9yLCBob3BlZnVsbHksIGltcHJvdmVkIHBlcmZvcm1hbmNlIChzcGVlZCkgaW4gY29tcHV0YXRpb24KIyBTdG9wSURfUnVuc19kdCA8LSBkYXRhLnRhYmxlKFN0b3BJRF9SdW5zX2RmKQojIHNldGtleShTdG9wSURfUnVuc19kdCwgUm93TnVtKQojIHN0cihTdG9wSURfUnVuc19kdCkKIyAKIyBBbGxEYXlzX1NvcnRlZF9kdCA8LSBkYXRhLnRhYmxlKEFsbERheXNfU29ydGVkKQojIHNldGtleShBbGxEYXlzX1NvcnRlZF9kdCwgUm93TnVtX09HKQojIHN0cihBbGxEYXlzX1NvcnRlZF9kdCkKIyAjIHJtKEFsbERheXNfU29ydGVkX2R0KQojIAojIAojICMgQWN0dWFsIGxvb3AgdG8gcGVyZm9ybSB0aGUgY29tcHV0YXRpb25zIGFuZCBsaW5rIHRvIG9yaWdpbmFsIGRhdGEgKEFsbERheXNfU29ydGVkX2R0KQojIEdyb3VwRGF0YSA8LSBsaXN0KCkKIyBmb3IoaSBpbiAxOm5yb3coU3RvcElEX1J1bnNfZHQpCiMgICAgKSB7CiMgICBhc3NpZ24ocGFzdGUwKCJncm91cF8iLCBpKSwKIyAgICAgICAgICAgIFN0b3BJRF9SdW5zX2R0W1Jvd051bSA9PSBpLCBSdW5zR3JvdXBdCiMgICAgICAgICAgICkKIyAKIyAgICAgIyMjIyMgIFRoZSBjb2RlIGJlbG93IGlzIHRoZSBzYW1lIGNvZGUgYXMgYWJvdmUsIGJ1dCBkb25lIHdpdGggZHBseXIgICMjIyMjCiMgCiMgICAgICMgYXNzaWduKHBhc3RlMCgiZ3JvdXBfIiwgaSksCiMgICAjICAgICAgICBmaWx0ZXIoU3RvcElEX1J1bnNfZGYsCiMgICAjICAgICAgICAgICAgICAgUm93TnVtID09IGkKIyAgICMgICAgICAgICAgICAgICkgJT4lIAojICAgIyAgICAgICAgICBzZWxlY3QoUnVuc0dyb3VwKQojICAgIyAgICAgICApCiMgCiMgICBhc3NpZ24ocGFzdGUwKCJncm91cF8iLCBpLCAiX3N0YXJ0IiksCiMgICAgICAgICAgU3RvcElEX1J1bnNfZHRbUm93TnVtID09IGksIHN0YXJ0c10KIyAgICAgICAgICkKIyAKIyAgIGFzc2lnbihwYXN0ZTAoImdyb3VwXyIsIGksICJfZW5kIiksCiMgICAgICAgICAgU3RvcElEX1J1bnNfZHRbUm93TnVtID09IGksIGVuZHNdCiMgICAgICAgICApCiMgCiMgICBhc3NpZ24ocGFzdGUwKCJncm91cF8iLCBpLCAiX3Jvd3MiKSwKIyAgICAgICAgICBBbGxEYXlzX1NvcnRlZF9kdFtSb3dOdW1fT0cgPj0gYXMubnVtZXJpYyhnZXQocGFzdGUwKCJncm91cF8iLCBpLCAiX3N0YXJ0IikKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICBSb3dOdW1fT0cgPD0gYXMubnVtZXJpYyhnZXQocGFzdGUwKCJncm91cF8iLCBpLCAiX2VuZCIpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICBSdW5zR3JvdXAgOj0gYXMuY2hhcmFjdGVyKGdldChwYXN0ZTAoImdyb3VwXyIsIGkpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAgICAgICAgICAgICAgICAgIF0KIyAKIyAgICAgIyMjIyMgIFRoZSBjb2RlIGJlbG93IGlzIHRoZSBzYW1lIGFzIHRoZSBjb2RlIGFib3ZlLCBidXQgZG9uZSB3aXRoIGRwbHlyICAjIyMjIwojIAojICAgICAgICAgICMgZmlsdGVyKEFsbERheXNfU29ydGVkLAojICAgICAgICAgICMgICAgICAgIGJldHdlZW4oUm93TnVtX09HLAojICAgICAgICAgICMgICAgICAgICAgICAgICAgYXMubnVtZXJpYyhnZXQocGFzdGUwKCJncm91cF8iLCBpLCAiX3N0YXJ0IikKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICksCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICBhcy5udW1lcmljKGdldChwYXN0ZTAoImdyb3VwXyIsIGksICJfZW5kIikKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICAgICAgICAgKQojICAgICAgICAgICMgICAgICAgKSAlPiUgCiMgICAgICAgICAgIyAgIG11dGF0ZShSdW5zR3JvdXAgPSBhcy5jaGFyYWN0ZXIoZ2V0KHBhc3RlMCgiZ3JvdXBfIiwgaSkKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICMgICAgICAgICkKIyAgICAgICAgICkKIyAKIyAgIEdyb3VwRGF0YVtbaV1dIDwtIGdldChwYXN0ZTAoImdyb3VwXyIsIGksICJfcm93cyIpKQojIAojICAgbWVzc2FnZSgiUHJvY2Vzc2luZyBHcm91cCAiLCBpLCAiIG9mIDIsODA5LDA2MiIpCiMgfQojIAojIAojIEdyb3VwRGF0YV9kZiA8LSByYmluZC5maWxsKEdyb3VwRGF0YSkKIyBzdHIoR3JvdXBEYXRhX2RmKQojIGhlYWQoR3JvdXBEYXRhX2RmKQojIHRhaWwoR3JvdXBEYXRhX2RmKQojICMgcm0oR3JvdXBEYXRhX2RmKQojIAojIAojIGdyb3VwXzEKIyBncm91cF8xX3N0YXJ0CiMgZ3JvdXBfMV9lbmQKIyBncm91cF8xX3Jvd3MKIyBncm91cF8yX3Jvd3MKIyBncm91cF8zX3Jvd3MKIyBncm91cF81MF9yb3dzCiMgc3RyKGdyb3VwXzUwX3Jvd3MpCiMgZ3JvdXBfMjgwOTA2Ml9yb3dzCiMgR3JvdXBEYXRhW1sxXV0KIyBHcm91cERhdGFbWzUwXV0KIyAKIyAKIyAjIyMjIyAgVGVzdGluZyBBcmVhIChCZWxvdykgICMjIyMjCiMgIyMjIyMgIFRlc3RpbmcgQXJlYSAoQmVsb3cpICAjIyMjIwojICMjIyMjICBUZXN0aW5nIEFyZWEgKEJlbG93KSAgIyMjIyMKIyAKIyAjIGhlYWQoU3RvcElEX1J1bnMkc3RhcnRzLCAyMCkKIyAjIGhlYWQoQWxsRGF5c19OZXdPcmRlciRTdG9wX0lELCAyMCkKIyAjIAojICMgCiMgIyBkYXQgPC0gYXMuZGF0YS5mcmFtZShjKDEsMSw3LDcsNyw5LDYsOCwyLDIsMiwxLDEsMSwxLDEpKQojICMgY29sbmFtZXMoZGF0KVsxXSA8LSAiZGF0IgojICMgciA8LSBybGUoZGF0JGRhdCkKIyAjIGRhdCRydW4gPC0gcmVwKHIkbGVuZ3RocywgciRsZW5ndGhzKQojICMgZGF0JHJ1bkxhZyA8LSBsYWcoZGF0JHJ1bikKIyAjIGRhdCRjb25kIDwtIHJlcChyJHZhbHVlcywgciRsZW5ndGhzKQojICMgZGF0CiMgIyBWaWV3KGRhdCkKCmBgYAoKCldoZW4gY29uc2VjdXRpdmUgU3RvcF9JRCBvY2N1cnJzLCBvbmx5IHRha2UgdGhlIGZpcnN0IG9jY3VycmVuY2UuIFRoaXMgaXMgZG9uZSBiZWNhdXNlIHRoZSBjb21wdXRhdGlvbiB0aW1lIHRvIHNlbGVjdCBvbmx5IHRoZSByZWNvcmQgd2l0aCB0aGUgbG9uZ2VzdCBEd2VsbF9UaW1lIGZvciBlYWNoIHJ1biB3YXMgdG9vIGxvbmcgKG92ZXIgNSBkYXlzKS4KClRoaXMgaXMgcHJvYmFibHkgbGVzcyB0aGFuIGlkZWFsIHdpdGggcmVnYXJkcyB0byBEd2VsbF9UaW1lLCBidXQgc2hvdWxkIG5vdCBtYWtlIG11Y2ggZGlmZmVyZW5jZSBmb3IgY2FsY3VsYXRpb25zIG9mIHRyYXZlbCB0aW1lLCBzcGVlZCwgZXRjLgpgYGB7cn0KCkFsbERheXNfRmlyc3RTdG9wSUQgPC0gQWxsRGF5c19TdG9wSUROZXdbU3RvcElEX1J1bnMkc3RhcnRzLCBdCgpkaW0oQWxsRGF5c19TdG9wSUROZXcpCmRpbShBbGxEYXlzX0ZpcnN0U3RvcElEKQoKbnJvdyhBbGxEYXlzX1N0b3BJRE5ldykgLSBucm93KEFsbERheXNfRmlyc3RTdG9wSUQpCgpybShBbGxEYXlzX1N0b3BJRE5ldykKcm0oU3RvcElEX1J1bnMpCnN0cihBbGxEYXlzX0ZpcnN0U3RvcElEKQoKYGBgCgoKRmVhdHVyZSBlbmdpbmVlcmluZy4KCkNyZWF0aW5nIG5ldyB2YXJpYWJsZXMuCmBgYHtyfQoKQWxsRGF5c19BZGRWYXJzIDwtIG11dGF0ZShBbGxEYXlzX0ZpcnN0U3RvcElELAogICAgICAgICAgICAgICAgICAgICAgICAgIE9kb21ldGVyX0Rpc3RhbmNlX01pID0gT2RvbWV0ZXJfRGlzdGFuY2UgLyA1MjgwLCAjNSwyODAgZmVldCBpbiAxIG1pbGUKICAgICAgICAgICAgICAgICAgICAgICAgICBEd2VsbF9UaW1lMiA9IGFzLm51bWVyaWMoRGVwYXJ0dXJlX1RpbWUgLSBFdmVudF9UaW1lKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX1lyID0gYXMuaW50ZWdlcih5ZWFyKEV2ZW50X1RpbWUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX010aCA9IGFzLmludGVnZXIobW9udGgoRXZlbnRfVGltZSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfRGF0ZSA9IGRheShFdmVudF9UaW1lKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0RheSA9IHdkYXkoRXZlbnRfVGltZSwgbGFiZWwgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyID0gaG91cihFdmVudF9UaW1lKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX01pbiA9IG1pbnV0ZShFdmVudF9UaW1lKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyR3JvdXAgPSBmYWN0b3IoaWZlbHNlKEV2ZW50X1RpbWVfSHIgPCAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMF8yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEV2ZW50X1RpbWVfSHIgPCA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwM181IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEV2ZW50X1RpbWVfSHIgPCA5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwNl84IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEV2ZW50X1RpbWVfSHIgPCAxMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDlfMTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRXZlbnRfVGltZV9IciA8IDE1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMTJfMTQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRXZlbnRfVGltZV9IciA8IDE4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMTVfMTciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRXZlbnRfVGltZV9IciA8IDIxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMThfMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRXZlbnRfVGltZV9IciA8IDI0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMjFfMjMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKSkpKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJHcm91cDBfMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwM181IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXA2XzgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDlfMTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDEyXzE0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAxNV8xNyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMThfMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDIxXzIzIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICApCgpybShBbGxEYXlzX0ZpcnN0U3RvcElEKQpzdHIoQWxsRGF5c19BZGRWYXJzKQoKCiMgZ3JvdXBfYnkoQWxsRGF5c19BZGRWYXJzLAojICAgICAgICAgIEV2ZW50X1RpbWVfSHJHcm91cAojICAgICAgICAgKSAlPiUgCiMgICBzdW1tYXJpc2UoQ250cyA9IG4oKQojICAgICAgICAgICAgKQoKCiMgVmlldyhoZWFkKGZpbHRlcihBbGxEYXlzX0FkZFZhcnMsCiMgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyID09IDAKIyAgICAgICAgICAgICAgICAgKSwKIyAgICAgICAgICAgNTAKIyAgICAgICAgICApCiMgICAgICkKCiMgVmlldyhoZWFkKEFsbERheXNfQWRkVmFycywgNTApKQoKYGBgCgoKPCEtLSBGdW5jdGlvbiBmb3IgY2FsY3VsYXRpbmcgdGhlIGRpc3RhbmNlIHRyYXZlbGVkIGJhc2VkIG9uIHRoZSBIYXZlcnNpbmUgZm9ybXVsYS4gIE9yaWdpbmFsIGNvZGUgZnJvbTogaHR0cHM6Ly93d3cuci1ibG9nZ2Vycy5jb20vZ3JlYXQtY2lyY2xlLWRpc3RhbmNlLWNhbGN1bGF0aW9ucy1pbi1yLyAtLT4KPCEtLSBgYGB7cn0gLS0+Cgo8IS0tIGdjZC5oZiA8LSBmdW5jdGlvbihsb25nMSwgbGF0MSwgbG9uZzIsIGxhdDIpIHsgLS0+CjwhLS0gICBSIDwtIDYzNzEgIyBFYXJ0aCBtZWFuIHJhZGl1cyBba21dIC0tPgo8IS0tICAgZGVsdGEubG9uZyA8LSAobG9uZzIgLSBsb25nMSkgLS0+CjwhLS0gICBkZWx0YS5sYXQgPC0gKGxhdDIgLSBsYXQxKSAtLT4KPCEtLSAgIGEgPC0gc2luKGRlbHRhLmxhdC8yKV4yICsgY29zKGxhdDEpICogY29zKGxhdDIpICogc2luKGRlbHRhLmxvbmcvMileMiAtLT4KPCEtLSAgIGMgPC0gMiAqIGFzaW4obWluKDEsc3FydChhKSkpIC0tPgo8IS0tICAgZCA9IFIgKiBjICogMC42MjEzNzEgIyAxIGttID0gMC42MjEzNzEgbWlsZXMgLS0+CjwhLS0gICByZXR1cm4oZCkgIyBEaXN0YW5jZSBpbiBtaWxlcyAtLT4KPCEtLSB9IC0tPgoKPCEtLSBgYGAgLS0+CgoKRmVhdHVyZSBlbmdpbmVlcmluZy4KCkNyZWF0aW5nIG1vcmUgdmFyaWFibGVzLiBDcmVhdGluZyBhIEJ1c0V2ZW50IHJvdyBudW1iZXIgZm9yIGZ1dHVyZSBpZGVudGlmaWNhdGlvbiBwdXJwb3Nlcy4gVGhlbiwgY3JlYXRpbmcgdmFyaW91cyB2YXJpYWJsZXMgdG8gYW5hbHl6ZSBkaXN0YW5jZSB0cmF2ZWxlZCBhbmQgc3BlZWQuCmBgYHtyfQoKQWxsRGF5c19CdXNEYXkgPC0gZ3JvdXBfYnkoQWxsRGF5c19BZGRWYXJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfRGF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShCdXNEYXlfRXZlbnROdW0gPSByb3dfbnVtYmVyKCksICAjIHVzZWQgdG8gaWRlbnRpZnkgQnVzIG1vdmVtZW50cyBvbiBhIHBhcnRpY3VsYXIgZGF0ZQogICAgICAgICAKICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2VfTGFnMSA9IGxhZyhPZG9tZXRlcl9EaXN0YW5jZSksCiAgICAgICAgIAogICAgICAgICBMYXRpdHVkZV9MMSA9IGxhZyhMYXRpdHVkZSksCiAgICAgICAgIExvbmdpdHVkZV9MMSA9IGxhZyhMb25naXR1ZGUpLAogICAgICAgICAjIExhdF9SYWRpYW4gPSBMYXRpdHVkZSpwaS8xODAsCiAgICAgICAgICMgTG9uZ19SYWRpYW4gPSBMb25naXR1ZGUqcGkvMTgwLAogICAgICAgICAjIExhdF9SYWRpYW5fTDEgPSBsYWcoTGF0X1JhZGlhbiksCiAgICAgICAgICMgTG9uZ19SYWRpYW5fTDEgPSBsYWcoTG9uZ19SYWRpYW4pLAogICAgICAgICAKICAgICAgICAgIyBhY2NvdW50aW5nIGZvciBwb3RlbnRpYWwgbmVnYXRpdmUgZGlzdGFuY2VzCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX0Z0ID0gaWZlbHNlKE9kb21ldGVyX0Rpc3RhbmNlID4gT2RvbWV0ZXJfRGlzdGFuY2VfTGFnMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2UgLSBPZG9tZXRlcl9EaXN0YW5jZV9MYWcxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID0gVHJhdmVsRGlzdGFuY2VfRnQgLyA1MjgwLCAjNSwyODAgZmVldCBpbiAxIG1pbGUKICAgICAgICAgCiAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWkyID0gZ2NkLmhmKGxvbmcxID0gTG9uZ19SYWRpYW5fTDEsCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdDEgPSBMYXRfUmFkaWFuX0wxLAogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb25nMiA9IExvbmdfUmFkaWFuLAogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXQyID0gTGF0X1JhZGlhbgogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzID0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaWZlbHNlKChpcy5uYShMb25naXR1ZGVfTDEpIHwgaXMubmEoTGF0aXR1ZGVfTDEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKGNiaW5kKExvbmdpdHVkZV9MMSwgTGF0aXR1ZGVfTDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNiaW5kKExvbmdpdHVkZSwgTGF0aXR1ZGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICogMC4wMDA2MjEzNzEsICMgMC4wMDA2MjEzNzEgbWlsZXMgPSAxIG1ldGVyCiAgICAgICAgIAogICAgICAgICAjIGFjY291bnRpbmcgZm9yIHBvdGVudGlhbCBuZWdhdGl2ZSB0aW1lcwogICAgICAgICBUcmF2ZWxUaW1lX1NlYyA9IGFzLm51bWVyaWMoaWZlbHNlKEV2ZW50X1RpbWUgPiBsYWcoRGVwYXJ0dXJlX1RpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWUgLSBsYWcoRGVwYXJ0dXJlX1RpbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRyYXZlbFRpbWVfSHIgPSBUcmF2ZWxUaW1lX1NlYyAvIDM2MDAsICMgMyw2MDAgc2Vjb25kcyBpbiAxIGhvdXIKICAgICAgICAgCiAgICAgICAgICMgYWNjb3VudGluZyBmb3IgcG90ZW50aWFsIG5lZ2F0aXZlIG9yIHplcm8gdHJhdmVsIHRpbWVzCiAgICAgICAgIFNwZWVkQXZnX01waCA9IGlmZWxzZShUcmF2ZWxUaW1lX0hyID4gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pIC8gVHJhdmVsVGltZV9IciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIAogICAgICAgICBTdGFydF9JRCA9IGxhZyhTdG9wSURfQ2xlYW4pLAogICAgICAgICBTdGFydF9EZXNjID0gbGFnKFN0b3BfRGVzYyksCiAgICAgICAgIFN0YXJ0U3RvcF9JRCA9IGlmZWxzZShpcy5uYShTdGFydF9JRCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZSgiTlVMTCIsIFN0b3BJRF9DbGVhbiwgc2VwID0gIi0tIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZShTdGFydF9JRCwgU3RvcElEX0NsZWFuLCBzZXAgPSAiLS0iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpCgoKcm0oQWxsRGF5c19BZGRWYXJzKQpzdHIoQWxsRGF5c19CdXNEYXkpCgojIHN1bW1hcnkoQWxsRGF5c19CdXNEYXkpCgojIFZpZXcodGFpbChBbGxEYXlzX0J1c0RheSwgNTApKQoKYGBgCgoKSW5zcGVjdGluZyBmb3IgaXNzdWVzIHdpdGggU3RhcnRTdG9wX0lEICh3aGVyZSB0aGUgdmFsdWUgaXMgZWl0aGVyIE5BIG9yIGNvbnRhaW5zIE5VTEwpLiBUaGV5IE9OTFkgZXhpc3Qgd2hlbiBCdXNEYXlfRXZlbnROdW0gPSAxICh3aGljaCBpcyBieSBkZXNpZ24pLiBTbyBldmVyeXRoaW5nIGxvb2tzIE9LLgpgYGB7cn0KClZpZXcoZ3JvdXBfYnkoQWxsRGF5c19CdXNEYXksCiAgICAgICAgICAgICAgU3RhcnRTdG9wX0lECiAgICAgICAgICAgICApICU+JSAKICAgICAgIHN1bW1hcmlzZSgKICAgICAgICAgQ250ID0gbigpCiAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhDbnQpCiAgICAgICAgICAgICAgKQogICAgKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19CdXNEYXksCiAgICAgICAgICAgIChpcy5uYShTdGFydFN0b3BfSUQpIHwKICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFN0YXJ0U3RvcF9JRCwgIk5VTEwiKQogICAgICAgICAgICApICYKICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICkKICAgICkKCmBgYAoKClN0YXRzIChxdWFudGlsZXMpIG92ZXJhbGwgZm9yIFRyYXZlbERpc3RhbmNlX01pLgpgYGB7cn0KClF1YW50aWxlc19kdCA8LSBBbGxEYXlzX0J1c0RheSAlPiUgCiAgbXV0YXRlKFREX01pX3EyID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuMDIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX3E5OCA9IHF1YW50aWxlKHggPSBUcmF2ZWxEaXN0YW5jZV9NaSwgcHJvYnMgPSAwLjk4LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfcTIgPSBxdWFudGlsZSh4ID0gVHJhdmVsVGltZV9TZWMsIHByb2JzID0gMC4wMiwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX3E5OCA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX1NlYywgcHJvYnMgPSAwLjk4LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9xMiA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuMDIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX3E5OCA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuOTgsIG5hLnJtID0gVFJVRSkKICAgICAgICApICU+JSAKICBkYXRhLnRhYmxlKCkKCgpTdGF0cyA8LSBRdWFudGlsZXNfZHQgJT4lIAogIG11dGF0ZShURF9NaV9NZWFuID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfTWVhbl9GID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaVtURF9NaV9xMiA8PSBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pIDw9IFREX01pX3E5OF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX01lZF9GID0gbWVkaWFuKFRyYXZlbERpc3RhbmNlX01pW1REX01pX3EyIDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pW1REX01pX3EyIDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfcTk4XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgCiAgICAgICAgIFRUX1NlY19NZWFuID0gbWVhbihUcmF2ZWxUaW1lX1NlYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX01lYW5fRiA9IG1lYW4oVHJhdmVsVGltZV9TZWNbVFRfU2VjX3EyIDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX3E5OF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19NZWQgPSBtZWRpYW4oVHJhdmVsVGltZV9TZWMsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfcTIgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUVF9TZWNfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykKICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9TZWNbVFRfU2VjX3EyIDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX3E5OF0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICksCgogICAgICAgICBUVF9Icl9NZWFuID0gbWVhbihUcmF2ZWxUaW1lX0hyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9NZWFuX0YgPSBtZWFuKFRyYXZlbFRpbWVfSHJbVFRfSHJfcTIgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX01lZCA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyW1RUX0hyX3EyIDw9IFRyYXZlbFRpbWVfSHIgJiBUcmF2ZWxUaW1lX0hyIDw9IFRUX0hyX3E5OF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX0NudCA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9IcikKICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfSHJfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfSHJbVFRfSHJfcTIgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfcTk4XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkgJT4lIAogIGRhdGEuZnJhbWUoKQoKcm0oQWxsRGF5c19CdXNEYXkpCnJtKFF1YW50aWxlc19kdCkKc3RyKFN0YXRzKQojIFZpZXcoaGVhZChTdGF0cywgNTApKQoKYGBgCgoKU3RhdHMgZm9yIFN0YXJ0U3RvcF9JRC4KYGBge3J9CgpRdWFudGlsZXNfU1NfZHQgPC0gZ3JvdXBfYnkoU3RhdHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFREX01pX1NTX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuMDUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX1NTX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxEaXN0YW5jZV9NaSwgcHJvYnMgPSAwLjk1LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfU1NfcTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsVGltZV9TZWMsIHByb2JzID0gMC4wNSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX1NlYywgcHJvYnMgPSAwLjk1LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU19xNSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuMDUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuOTUsIG5hLnJtID0gVFJVRSkKICAgICAgICApICU+JSAKICBkYXRhLnRhYmxlKCkKCgpTdGF0c19TdFN0IDwtIGdyb3VwX2J5KFF1YW50aWxlc19TU19kdCwKICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQKICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShURF9NaV9TU19NZWFuID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfU1NfTWVhbl9GID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaVtURF9NaV9TU19xNSA8PSBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pIDw9IFREX01pX1NTX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9TU19NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX1NTX01lZF9GID0gbWVkaWFuKFRyYXZlbERpc3RhbmNlX01pW1REX01pX1NTX3E1IDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfU1NfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfU1NfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pW1REX01pX1NTX3E1IDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfU1NfcTk1XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgCiAgICAgICAgIFRUX1NlY19TU19NZWFuID0gbWVhbihUcmF2ZWxUaW1lX1NlYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTX01lYW5fRiA9IG1lYW4oVHJhdmVsVGltZV9TZWNbVFRfU2VjX1NTX3E1IDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX1NTX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19TU19NZWQgPSBtZWRpYW4oVHJhdmVsVGltZV9TZWMsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19TU19NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfU1NfcTUgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUVF9TZWNfU1NfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykpLAogICAgICAgICBUVF9TZWNfU1NfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfU2VjW1RUX1NlY19TU19xNSA8PSBUcmF2ZWxUaW1lX1NlYyAmIFRyYXZlbFRpbWVfU2VjIDw9IFRUX1NlY19TU19xOTVdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCgogICAgICAgICBUVF9Icl9TU19NZWFuID0gbWVhbihUcmF2ZWxUaW1lX0hyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU19NZWFuX0YgPSBtZWFuKFRyYXZlbFRpbWVfSHJbVFRfSHJfU1NfcTUgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX1NTX01lZCA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU19NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyW1RUX0hyX1NTX3E1IDw9IFRyYXZlbFRpbWVfSHIgJiBUcmF2ZWxUaW1lX0hyIDw9IFRUX0hyX1NTX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX1NTX0NudCA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9IcikpLAogICAgICAgICBUVF9Icl9TU19DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9IcltUVF9Icl9TU19xNSA8PSBUcmF2ZWxUaW1lX0hyICYgVHJhdmVsVGltZV9IciA8PSBUVF9Icl9TU19xOTVdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKSAlPiUgCiAgZGF0YS5mcmFtZSgpCgpybShTdGF0cykKcm0oUXVhbnRpbGVzX1NTX2R0KQpzdHIoU3RhdHNfU3RTdCkKIyBWaWV3KGhlYWQoU3RhdHNfU3RTdCwgNTApKQoKYGBgCgoKU3RhdHMgZm9yIFN0YXJ0U3RvcF9JRCB3aXRoIEV2ZW50X1RpbWVfSHJHcm91cC4KYGBge3J9CgpRdWFudGlsZXNfU1NIR19kdCA8LSBncm91cF9ieShTdGF0c19TdFN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfSHJHcm91cAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShURF9NaV9TU0hHX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuMDUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX1NTSEdfcTk1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuOTUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19TU0hHX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfU2VjLCBwcm9icyA9IDAuMDUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19TU0hHX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX1NlYywgcHJvYnMgPSAwLjk1LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU0hHX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfSHIsIHByb2JzID0gMC4wNSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfSHJfU1NIR19xOTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsVGltZV9IciwgcHJvYnMgPSAwLjk1LCBuYS5ybSA9IFRSVUUpCiAgICAgICAgKSAlPiUgCiAgZGF0YS50YWJsZSgpCgoKU3RhdHNfU3RTdF9IckdycCA8LSBncm91cF9ieShRdWFudGlsZXNfU1NIR19kdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoVERfTWlfU1NIR19NZWFuID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfU1NIR19NZWFuX0YgPSBtZWFuKFRyYXZlbERpc3RhbmNlX01pW1REX01pX1NTSEdfcTUgPD0gVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaSA8PSBURF9NaV9TU0hHX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfU1NIR19NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFREX01pX1NTSEdfTWVkX0YgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWlbVERfTWlfU1NIR19xNSA8PSBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pIDw9IFREX01pX1NTSEdfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFREX01pX1NTSEdfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9TU0hHX0NudF9GID0gc3VtKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaVtURF9NaV9TU0hHX3E1IDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfU1NIR19xOTVdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgCiAgICAgICAgIFRUX1NlY19TU0hHX01lYW4gPSBtZWFuKFRyYXZlbFRpbWVfU2VjLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfU1NIR19NZWFuX0YgPSBtZWFuKFRyYXZlbFRpbWVfU2VjW1RUX1NlY19TU0hHX3E1IDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX1NTSEdfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19TU0hHX01lZCA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTSEdfTWVkX0YgPSBtZWRpYW4oVHJhdmVsVGltZV9TZWNbVFRfU2VjX1NTSEdfcTUgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfU1NIR19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUVF9TZWNfU1NIR19DbnQgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSksCiAgICAgICAgIFRUX1NlY19TU0hHX0NudF9GID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfU1NIR19xNSA8PSBUcmF2ZWxUaW1lX1NlYyAmIFRyYXZlbFRpbWVfU2VjIDw9IFRUX1NlY19TU0hHX3E5NV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCgogICAgICAgICBUVF9Icl9TU0hHX01lYW4gPSBtZWFuKFRyYXZlbFRpbWVfSHIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTSEdfTWVhbl9GID0gbWVhbihUcmF2ZWxUaW1lX0hyW1RUX0hyX1NTSEdfcTUgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfU1NIR19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX1NTSEdfTWVkID0gbWVkaWFuKFRyYXZlbFRpbWVfSHIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTSEdfTWVkX0YgPSBtZWRpYW4oVHJhdmVsVGltZV9IcltUVF9Icl9TU0hHX3E1IDw9IFRyYXZlbFRpbWVfSHIgJiBUcmF2ZWxUaW1lX0hyIDw9IFRUX0hyX1NTSEdfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX0hyX1NTSEdfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX0hyKSksCiAgICAgICAgIFRUX0hyX1NTSEdfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfSHJbVFRfSHJfU1NIR19xNSA8PSBUcmF2ZWxUaW1lX0hyICYgVHJhdmVsVGltZV9IciA8PSBUVF9Icl9TU0hHX3E5NV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKSAlPiUgCiAgZGF0YS5mcmFtZSgpCgpybShTdGF0c19TdFN0KQpybShRdWFudGlsZXNfU1NIR19kdCkKc3RyKFN0YXRzX1N0U3RfSHJHcnApCiMgVmlldyhoZWFkKFN0YXRzX1N0U3RfSHJHcnAsIDUwKSkKCmBgYAoKCkZlYXR1cmUgZW5naW5lZXJpbmcuCgpDcmVhdGluZyBhIEJ1c0V2ZW50Um91dGUgcm93IG51bWJlciwgYW5kIGEgUm91dGVBbHRfTGFnMSBpbmRpY2F0b3IgZm9yIGZ1dHVyZSBpZGVudGlmaWNhdGlvbiBwdXJwb3Nlcy4gCmBgYHtyfQoKIyBybShRdWFudGlsZXNfZHQpCiMgcm0oUXVhbnRpbGVzX1NTX2R0KQojIHJtKEFsbERheXNfQnVzRGF5KQojIHJtKFF1YW50aWxlc19TU0hHX2R0KQojIHJtKFN0YXRzX1N0U3QpCgpBbGxEYXlzX0J1c0RheVJvdXRlIDwtIGdyb3VwX2J5KFN0YXRzX1N0U3RfSHJHcnAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQnVzX0lELAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfRGF0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSb3V0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFJvdXRlQWx0X0xhZzEgPSBsYWcoUm91dGVBbHQpICAjIHVzZWQgaW4gZnV0dXJlIGFuYWx5c2VzIHRvIGlkZW50aWZ5IFJvdXRlIGNoYW5nZXMKICAgICAgICAgIyBPZG9tZXRlcl9EaXN0YW5jZV9MYWcxID0gbGFnKE9kb21ldGVyX0Rpc3RhbmNlKSwKICAgICAgICAgIyAKICAgICAgICAgIyAjIGFjY291bnRpbmcgZm9yIHBvdGVudGlhbCBuZWdhdGl2ZSBkaXN0YW5jZXMKICAgICAgICAgIyBUcmF2ZWxEaXN0YW5jZV9GdCA9IGlmZWxzZShPZG9tZXRlcl9EaXN0YW5jZSA+PSBPZG9tZXRlcl9EaXN0YW5jZV9MYWcxLAogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9kb21ldGVyX0Rpc3RhbmNlIC0gT2RvbWV0ZXJfRGlzdGFuY2VfTGFnMSwKICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQQogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgIyBUcmF2ZWxEaXN0YW5jZV9NaSA9IFRyYXZlbERpc3RhbmNlX0Z0IC8gNTI4MCwgIzUsMjgwIGZlZXQgaW4gMSBtaWxlCiAgICAgICAgICMgCiAgICAgICAgICMgIyBhY2NvdW50aW5nIGZvciBwb3RlbnRpYWwgbmVnYXRpdmUgdGltZXMKICAgICAgICAgIyBUcmF2ZWxUaW1lX1NlYyA9IGFzLm51bWVyaWMoaWZlbHNlKEV2ZW50X1RpbWUgPj0gbGFnKERlcGFydHVyZV9UaW1lKSwKICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWUgLSBsYWcoRGVwYXJ0dXJlX1RpbWUpLAogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEKICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICMgVHJhdmVsVGltZV9IciA9IFRyYXZlbFRpbWVfU2VjIC8gMzYwMCwgIyAzLDYwMCBzZWNvbmRzIGluIDEgaG91cgogICAgICAgICAjIAogICAgICAgICAjICMgYWNjb3VudGluZyBmb3IgcG90ZW50aWFsIG5lZ2F0aXZlIG9yIHplcm8gdHJhdmVsIHRpbWVzCiAgICAgICAgICMgU3BlZWRBdmdfTXBoID0gaWZlbHNlKFRyYXZlbFRpbWVfSHIgPiAwLAogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSAvIFRyYXZlbFRpbWVfSHIsCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgIE5BCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkgJT4lIAogIGRhdGEuZnJhbWUoKQoKcm0oU3RhdHNfU3RTdF9IckdycCkKc3RyKEFsbERheXNfQnVzRGF5Um91dGUpCgpgYGAKCgpGZWF0dXJlIGVuZ2luZWVyaW5nLgoKQ2FsY3VsYXRpbmcgYSB2YXJpYWJsZSB0byBrbm93IGlmIHRoZSBSb3V0ZUFsdCBjaGFuZ2VkLiBDb3VsZCBiZSB1c2VmdWwgaW4gaGVscGluZyBpZGVudGlmeWluZyB3ZWlyZG5lc3MgaW4gY2FsY3VsYXRlZCBkaXN0YW5jZXMgYW5kIHNwZWVkcy4KYGBge3J9CgojIHJtKFN0YXRzX1N0U3RfSHJHcnApCgpBbGxEYXlzX0RpckNoYW5nZSA8LSBBbGxEYXlzX0J1c0RheVJvdXRlICU+JSAKICBtdXRhdGUoRGlyQ2hhbmdlID0gaWZlbHNlKFJvdXRlQWx0ID09IFJvdXRlQWx0X0xhZzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2FtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hhbmdlIgogICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBEaXJDaGFuZ2UyID0gZmFjdG9yKGlmZWxzZShpcy5uYShEaXJDaGFuZ2UpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ2hhbmdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlyQ2hhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkKCnJtKEFsbERheXNfQnVzRGF5Um91dGUpCnN0cihBbGxEYXlzX0RpckNoYW5nZSkKCmBgYAoKClJlLW9yZGVyaW5nIHRoZSB2YXJpYWJsZXMgdG8gZWFzZSB3aXRoIGNvbXByZWhlbnNpb24uCmBgYHtyfQoKQWxsRGF5c19OZXdPcmRlciA8LSAgc2VsZWN0KEFsbERheXNfRGlyQ2hhbmdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUm93TnVtX09HLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSb3V0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJvdXRlQWx0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSb3V0ZUFsdF9MYWcxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlyQ2hhbmdlMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJvdXRlX0RpcmVjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0b3BfU2VxdWVuY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0X0Rlc2MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdG9wSURfQ2xlYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdG9wSURfSW5kaWNhdG9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9EZXNjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X0Rlc2NyaXB0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9ZciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfTXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9EYXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9EYXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9NaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVwYXJ0dXJlX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEd2VsbF9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRHdlbGxfVGltZTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgTGF0aXR1ZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb25naXR1ZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBIZWFkaW5nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZG9tZXRlcl9EaXN0YW5jZV9MYWcxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9GdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX3EyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfcTk4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19xOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU0hHX3E1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19xOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX01lYW5fRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfTWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfTWVkX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfTWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX0NudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX0NudF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU0hHX0NudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19xMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19xOTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfcTk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19xOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfTWVkX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX0NudF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX0hyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfcTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9xOTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19xNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX3E5NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTSEdfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU0hHX3E5NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU0hHX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTSEdfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNwZWVkQXZnX01waAogICAgICAgICAgICAgICAgICAgICAgICAgICApCgpybShBbGxEYXlzX0RpckNoYW5nZSkKc3RyKEFsbERheXNfTmV3T3JkZXIpCgojIFZpZXcoaGVhZChBbGxEYXlzX05ld09yZGVyLCA1MDApKQojIFZpZXcodGFpbChBbGxEYXlzX05ld09yZGVyLCA1MDApKQoKYGBgCgoKU3VtbWFyaXppbmcgdGhlIGRhdGEgdG8gaGVscCBzcG90IGFub21vbGllcy4KYGBge3J9CgpzdW1tYXJ5KEFsbERheXNfTmV3T3JkZXIpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKVmlldyhUcmF2RGlzdE1pX1BjdGlsZXMpOiA5OSUgb2YgVHJhdmVsRGlzdGFuY2VfTWkgYXJlIGFib3V0IDEgbWlsZSBvciBsZXNzLi4uYnV0IHNvbWUgd2VpcmQgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIChlLmcuLCA1ODQgbWlsZXMgdHJhdmVsZWQpIGV4aXN0LgpgYGB7cn0KClRyYXZEaXN0TWlfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShBbGxEYXlzX05ld09yZGVyJFRyYXZlbERpc3RhbmNlX01pKSAlPiUgCiAgbXV0YXRlKCNQY3RpbGUgPSBudGlsZShBbGxEYXlzX05ld09yZGVyJFRyYXZlbERpc3RhbmNlX01pLCAxMDApLAogICAgICAgICAjTWluUiA9IG1pbl9yYW5rKEFsbERheXNfTmV3T3JkZXIkVHJhdmVsRGlzdGFuY2VfTWkpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3T3JkZXIkVHJhdmVsRGlzdGFuY2VfTWkpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoVHJhdkRpc3RNaV9OdGlsZSlbMV0gPC0gIlRyYXZlbERpc3RhbmNlX01pIgojIHN0cihUcmF2RGlzdE1pX050aWxlKQoKVHJhdkRpc3RNaV9OdGlsZV9Sb3dzIDwtIG5yb3coVHJhdkRpc3RNaV9OdGlsZSkKCiMgVmlldyh0YWlsKFRyYXZEaXN0TWlfTnRpbGUsIDUwMCkpCgoKVHJhdkRpc3RNaV9QY3RpbGVzIDwtIGdyb3VwX2J5KFRyYXZEaXN0TWlfTnRpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblRyYXZEaXN0TWlBdFBjdGlsZSA9IG1pbihUcmF2ZWxEaXN0YW5jZV9NaSksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBUcmF2RGlzdE1pX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpCiAgICAgICAgKQoKcm0oVHJhdkRpc3RNaV9OdGlsZSkKcm0oVHJhdkRpc3RNaV9OdGlsZV9Sb3dzKQoKVmlldyhUcmF2RGlzdE1pX1BjdGlsZXMpClRyYXZEaXN0TWlfUGN0aWxlcwoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaS4KCldoeSBhcmUgc29tZSBUcmF2ZWxEaXN0YW5jZV9NaSAiTkEiPyBJdCBsb29rcyBsaWtlIHBhcnRpYWxseSBiZWNhdXNlIHRoZSByZWNvcmRzIGFyZSB0aGUgZmlyc3QgdHJpcCBvZiB0aGUgZGF5IChmb3IgdGhhdCBidXMpLCBzbyBJIHB1cnBvc2VmdWxseSBzZXQgdGhlIGRpc3RhbmNlIHRvICJOQSIuIEFub3RoZXIgcmVhc29uIGlzIGR1ZSB0byB0aGUgb2RvbWV0ZXIgcmVjb3JkaW5nIGEgdmFsdWUgbGVzcyB0aGFuIHRoZSBwcmV2aW91cyBvZG9tZXRlciByZWNvcmRpbmcuIEluIG1vc3QgY2FzZXMsIEkgaGF2ZSBubyBleHBsYW5hdGlvbiBmb3IgdGhpcyAtIHRob3VnaCBJIGhhdmUgb2JzZXJ2ZWQgYWJvdXQgNjclIG9mIGFsbCBpbnN0YW5jZXMgd2hlcmUgVHJhdmVsRGlzdGFuY2VfTWkgaXMgTkEgKG90aGVyIHRoYW4gYmVjYXVzZSBpdCdzIHRoZSBmaXJzdCByZWNvcmQgb2YgdGhlIGRheSkgYXJlIGluc3RhbmNlcyB3aGVyZSBEaXJDaGFuZ2UyIGlzICJDaGFuZ2UiLiBUaGlzIGlzIHdlaXJkIGFuZCBzaG91bGQgYmUgYXNrZWQgdG8gV01BVEEuCmBgYHtyfQoKIyBWaWV3KGhlYWQoQWxsRGF5c19OZXdPcmRlciwgNTAwKSkKClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICMgV2hlbiBCdXNEYXlfRXZlbnROdW0gPT0gMSwgVHJhdmVsRGlzdGFuY2VfTWkgaXMgTkEgYnkgZGVzaWduIChkb24ndCB3YW50IHRvIGNhbGN1bGF0ZSBkaXN0YW5jZSBiYXNlZCBvbiB5ZXN0ZXJkYXkncyBwb3NpdGlvbikKICAgICAgICAgICApICU+JSAKICAgICAgIGdyb3VwX2J5KFN0YXJ0U3RvcF9JRCkgJT4lIAogICAgICAgc3VtbWFyaXNlKENudHMgPSBzdW0oaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShkZXNjKENudHMpCiAgICAgICAgICAgICAgKQogICAgKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgU3RhcnRTdG9wX0lEID09ICIxMDAwMjQ1LS0xMDAwMjExIgogICAgICAgICAgICkgJT4lIAogICAgICAgc2VsZWN0KFJvd051bV9PRywKICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgRXZlbnRfVGltZSwKICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyR3JvdXAsCiAgICAgICAgICAgICAgQnVzX0lELAogICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbiwKICAgICAgICAgICAgICBURF9NaV9TU19NZWFuX0YsCiAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWFuLAogICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgIFREX01pX1NTX01lZCwKICAgICAgICAgICAgICBURF9NaV9TU19NZWRfRiwKICAgICAgICAgICAgICBURF9NaV9TU0hHX01lZCwKICAgICAgICAgICAgICBURF9NaV9TU0hHX01lZF9GLAogICAgICAgICAgICAgIFREX01pX1NTX0NudCwKICAgICAgICAgICAgICBURF9NaV9TU19DbnRfRiwKICAgICAgICAgICAgICBURF9NaV9TU0hHX0NudCwKICAgICAgICAgICAgICBURF9NaV9TU0hHX0NudF9GCiAgICAgICAgICAgICAgKSAlPiUgCiAgICAgICBtdXRhdGUoUmF0aW9fTWVhblRvSHZycyA9IFREX01pX1NTX01lYW4gLyBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzKSAlPiUgCiAgICAgICBhcnJhbmdlKEV2ZW50X1RpbWUpCiAgICApCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICApCiAgICApCgojIFRoZXNlIHJlY29yZHMgYXJlIE5BIGJlY3Vhc2UgdGhlIHJlY29yZCBpcyB0aGUgZmlyc3QgcmVjb3JkIG9mIHRoZSBkYXkgKHRoZSBFdmVudF9UaW1lX0RhdGUpClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAzMjYsIDM0NikgfCAjIDMzNgogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA1OTEsIDYxMSkgfCAjIDYwMQogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA4NDUsIDg2NSkgIyA4NTUKICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKVGhlc2UgcmVjb3JkcyBhcmUgTkEgYmVjdWFzZSB0aGUgY3VycmVudCByZWNvcmQgb2RvbWV0ZXIgaXMgbGVzcyB0aGFuIHRoZSBwcmV2aW91cyByZWNvcmQgb2RvbWV0ZXIuIFRoZW9yZXRpY2FsbHksIHRoaXMgc2hvdWxkIE5PVCBoYXBwZW4uIE1lOiBpdCBhcHBlYXJzIHRoYXQgYWJvdXQgNjclIG9mIGFsbCBpbnN0YW5jZXMgd2hlcmUgVHJhdmVsRGlzdGFuY2VfTWkgaXMgTkEgKG90aGVyIHRoYW4gYmVjYXVzZSBpdCdzIHRoIGZpcnN0IHJlY29yZCBvZiB0aGUgZGF5KSBhcmUgaW5zdGFuY2VzIHdoZXJlIERpckNoYW5nZTIgaXMgIkNoYW5nZSIuIFRoaXMgaXMgd2VpcmQgYW5kIHNob3VsZCBiZSBhc2tlZCB0byBXTUFUQS4KYGBge3J9CgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMTk0LCAyMTQpIHwgIyAyMDQKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDQwLCA0NjApIHwgIyA0NTAKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDc4LCA0OTgpIHwgIyA0ODgKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNTEwLCA1MzApICMgNTIwCiAgICAgICAgICAgKQogICAgKQoKVGVzdFRhYmxlIDwtIGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxCiAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoVHJhdmVsRGlzdGFuY2VfTkEgPSBhcy5mYWN0b3IoaWZlbHNlKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUcnVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGYWxzZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICApICU+JQogIGdyb3VwX2J5KERpckNoYW5nZTIsIFRyYXZlbERpc3RhbmNlX05BKSAlPiUKICBzdW1tYXJpc2UoVHJhdkRpc3RNaV9OQUNudHMgPSBuKCkKICAgICAgICAgICApCgojIFRlc3RUYWJsZQoKVGVzdFRhYmxlX1NwcmVhZCA8LSBhcy5kYXRhLmZyYW1lKHNwcmVhZChUZXN0VGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdkRpc3RNaV9OQUNudHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc2VsZWN0KEZhbHNlLAogICAgICAgICBUcnVlCiAgICAgICAgKQoKcm93Lm5hbWVzKFRlc3RUYWJsZV9TcHJlYWQpIDwtIGMoIkNoYW5nZSIsICJTYW1lIikKIyBzdHIoVGVzdFRhYmxlX1NwcmVhZCkKIyBUZXN0VGFibGVfU3ByZWFkCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChUZXN0VGFibGVfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAxCiAgICAgICAgICApCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChUZXN0VGFibGVfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAyCiAgICAgICAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKTGV0J3MgbG9vayBhdCBqdXN0IHRoZSBUcmF2ZWxEaXN0YW5jZV9NaSB2YWx1ZXMgdGhhdCBhcmUgTk9UICJOQSIuCmBgYHtyfQoKcm0oVGVzdFRhYmxlKQpybShUZXN0VGFibGVfU3ByZWFkKQoKVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSA8LSBmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBUcmF2ZWxEaXN0YW5jZV9NaSAhPSAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCmRpbShBbGxEYXlzX05ld09yZGVyKQpkaW0oVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSkKbnJvdyhBbGxEYXlzX05ld09yZGVyKSAtIG5yb3coVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSkKCnN0cihUcmF2ZWxEaXN0YW5jZV9NaV9Ob05BKQpzdW1tYXJ5KFRyYXZlbERpc3RhbmNlX01pX05vTkEpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKTGV0J3MgcGxvdCBqdXN0IHRoZSBUcmF2ZWxEaXN0YW5jZV9NaSB2YWx1ZXMgdGhhdCBhcmUgTk9UICJOQSIuCmBgYHtyfQoKVHJhdkRpc3RNaV9IaXN0RGVuIDwtIGdncGxvdChzZWxlY3QoVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAuLmRlbnNpdHkuLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wNSwgZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvdXIgPSAiZ3JleTYwIiwgc2l6ZSA9IDAuMikgKwogIGdlb21fbGluZShzdGF0ID0gImRlbnNpdHkiLCBjb2xvdXIgPSAicmVkIikgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAxLjUpLCB5bGltID0gYygwLCA0LjApCiAgICAgICAgICAgICAgICAgKSArCiAgbGFicyh0aXRsZSA9ICJWYXJpYXRpb24gaW4gRGlzdGFuY2UgQmV0d2VlbiBTdG9wcyIsCiAgICAgICB4ID0gIlRyYXZlbCBEaXN0YW5jZSAobWlsZXMpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIKICAgICAgKQoKVHJhdkRpc3RNaV9IaXN0RGVuCgpgYGAKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkuCgpMb29raW5nIGF0IHRoZSBleHRyZW1lbHkgbGFyZ2UgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzLiBTb21lIChhcHJveCAyNyUpIG9mIFRyYXZlbERpc3RhbmNlX01pIHZhbHVlcyA+IDEgbWlsZSBhcmUgd2hlbiB0aGUgRGlyQ2hhbmdlMiBjaGFuZ2VzLi4uYnV0IHdoYXQgYWJvdXQgdGhlIG90aGVyIH43MyU/CmBgYHtyfQoKcm0oVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSkKCiMgZXhhbXBsZXMgb2Ygd2VpcmRseSBsYXJnZSBUcmF2ZWxEaXN0YW5jZV9NaQpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSA+IDEuMTU4NzEyMTIxMiAjIDEuMTU4NzEyMTIxMiBpcyB0aGUgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsRGlzdGFuY2VfTWkpCiAgICAgICAgICAgICAgKQogICAgKQoKCiMgV2h5IGFyZSB0aGVzZSBleHRyZW1lcz8gIEFpcnBvcnRzPyAgQnVzIGNvbGxlY3Rpb24gcG9pbnRzPwpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQwNDQsIDQ5NDA2NCkgfCAjIDQ5NDA1NAogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQyNzMsIDQ5NDI5MykgfCAjIDQ5NDI4MwogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQ2MjYsIDQ5NDY0NikgfCAjIDQ5NDYzNgogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAxNjEwMTU2LCAxNjEwMTc2KSB8ICMgMTYxMDE2NgogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAyMDczMDc0LCAyMDczMDk0KSAjIDIwNzMwODQKICAgICAgICAgICApCiAgICApCgojIEJlZm9yZSBSZW1vdmluZyBSdW5zCiMgVmlldyhmaWx0ZXIoQWxsRGF5c19Tb3J0ZWQsCiMgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDQ5NDA0NCwgNDk0MDY0KSB8ICMgNDk0MDU0CiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0MjczLCA0OTQyOTMpIHwgIyA0OTQyODMKIyAgICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQ2MjYsIDQ5NDY0NikgfCAjIDQ5NDYzNgojICAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDE2MTAxNTYsIDE2MTAxNzYpIHwgIyAxNjEwMTY2CiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMjA3MzA3NCwgMjA3MzA5NCkgIyAyMDczMDg0CiMgICAgICAgICAgICApCiMgICAgICkKCiMgQWZ0ZXIgUmVtb3ZpbmcgUnVucwojIFZpZXcoZmlsdGVyKEFsbERheXNfRmlyc3RTdG9wSUQsCiMgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDQ5NDA0NCwgNDk0MDY0KSB8ICMgNDk0MDU0CiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0MjczLCA0OTQyOTMpIHwgIyA0OTQyODMKIyAgICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQ2MjYsIDQ5NDY0NikgfCAjIDQ5NDYzNgojICAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDE2MTAxNTYsIDE2MTAxNzYpIHwgIyAxNjEwMTY2CiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMjA3MzA3NCwgMjA3MzA5NCkgIyAyMDczMDg0CiMgICAgICAgICAgICApCiMgICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkuCgpBbnkgcmVsYXRpb24gd2l0aCBEaXJDaGFuZ2UyPyAgRG9lc24ndCBsb29rIGFzIGlmIHRoaXMgaXMgc28uCmBgYHtyfQoKRXh0cmVtZVRyYXZEaXN0IDwtIGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShUcmF2RGlzdF9FeHRyZW1lID0gaWZlbHNlKFRyYXZlbERpc3RhbmNlX01pID4gMS4xNTg3MTIxMjEyLCAjIDEuMTU4NzEyMTIxMiBpcyB0aGUgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRydWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGYWxzZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBncm91cF9ieShEaXJDaGFuZ2UyLCBUcmF2RGlzdF9FeHRyZW1lKSAlPiUgCiAgc3VtbWFyaXNlKFRyYXZEaXN0TUlfRXh0Q250cyA9IG4oKQogICAgICAgICAgICkKCiMgRXh0cmVtZVRyYXZEaXN0CgoKRXh0cmVtZVRyYXZEaXN0X1NwcmVhZCA8LSBhcy5kYXRhLmZyYW1lKHNwcmVhZChFeHRyZW1lVHJhdkRpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdkRpc3RfRXh0cmVtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2RGlzdE1JX0V4dENudHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc2VsZWN0KEZhbHNlLAogICAgICAgICBUcnVlCiAgICAgICAgKQoKcm93Lm5hbWVzKEV4dHJlbWVUcmF2RGlzdF9TcHJlYWQpIDwtIGMoIkNoYW5nZSIsICJTYW1lIikKIyBzdHIoRXh0cmVtZVRyYXZEaXN0X1NwcmVhZCkKIyBFeHRyZW1lVHJhdkRpc3RfU3ByZWFkCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChFeHRyZW1lVHJhdkRpc3RfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAxCiAgICAgICAgICApCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChFeHRyZW1lVHJhdkRpc3RfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAyCiAgICAgICAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKTG9va2luZyBhdCBzcGVjaWZpYyBidXNlcyBhbmQgU3RhcnRTdG9wX0lELgpgYGB7cn0KCnJtKEV4dHJlbWVUcmF2RGlzdCkKcm0oRXh0cmVtZVRyYXZEaXN0X1NwcmVhZCkKClZpZXcoYXJyYW5nZShncm91cF9ieShBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgICAgQnVzX0lECiAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogICAgICAgICAgICAgICBzdW1tYXJpc2UoRGlzdFRyYXZfTWVhbiA9IG1lYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICBEaXN0VHJhdl9NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSkKICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgIGRlc2MoRGlzdFRyYXZfTWVkKQogICAgICAgICAgICApCiAgICApCgoKIyBleGFtcGxlIG9mIGV4dHJlbWVseSBzbWFsbCBUcmF2ZWxEaXN0YW5jZV9NaSB2YWx1ZXMgKGxvb2tzIGxpa2UgdGhlIG9kb21ldGVyIHdhc24ndCBmdW5jdGlvbmluZykKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgQnVzX0lEID09IDYxMTEgfAogICAgICAgICAgICAgIEJ1c19JRCA9PSA3MjAxIHwKICAgICAgICAgICAgICBCdXNfSUQgPT0gODA1OAogICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShCdXNfSUQsIEV2ZW50X1RpbWUpCiAgICApCgoKVmlldyhhcnJhbmdlKGdyb3VwX2J5KEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQKICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgICAgICAgICAgICAgIHN1bW1hcmlzZShEaXN0VHJhdl9NZWFuID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgICAgICAgIERpc3RUcmF2X01lZCA9IG1lZGlhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKQogICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgZGVzYyhEaXN0VHJhdl9NZWQpCiAgICAgICAgICAgICkKICAgICkKCiMgZXhhbXBsZSBvZiBleHRyZW1lbHkgbGFyZ2UgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzLi4ubm8gaWRlYSB3aHkuLi4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgU3RhcnRTdG9wX0lEID09ICIxMDAzNjY1LS0xMiIgfAogICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCA9PSAiMTAwMzY2NS0tNTAwMTkyNSIgfAogICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCA9PSAiMzAwMTAzOC0tMzAwMjU2NSIKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoU3RhcnRTdG9wX0lELCBFdmVudF9UaW1lKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pX05ldy4KCklmIFRyYXZlbERpc250YWNlX01pIGlzIGJlbG93IHRoZSA1dGggcGVyY2VudGlsZSBmb3IgdGhhdCBTdGFydFN0b3BfSUQsIG9yIGlmIFRyYXZlbERpc250YWNlX01pIGlzIGFib3ZlIHRoZSA5NXRoIHBlcmNlbnRpbGUgZm9yIHRoYXQgU3RhcnRTdG9wX0lELCBvciBpZiBUcmF2ZWxEaXN0YW5jZV9NaSBpcyBOQSAod2hlbiB0aGUgQnVzRGF5X0V2ZW50TnVtICE9MSksIGNvbnNpZGVyIHRoaXMgYW4gb3V0bGllci4gIEluIHRoaXMgY2FzZSwgcmVwbGFjZSB0aGUgdmFsdWUgd2l0aCB0aGUgbWVhbiBmb3IgdGhhdCBTdGFydFN0b3BfSUQgYW5kIEhvdXJHcm91cCAoVERfTWlfU1NIR19NZWFuX0YpLCBvciBpZiB0aGVyZSBhcmUgbm90IGVub3VnaCB2YWx1ZXMgYXQgdGhlIEhvdXJHcm91cCBsZXZlbCwgcmVwbGFjZSBpdCB3aXRoIHRoZSBtZWFuIGZvciB0aGF0IFN0YXJ0U3RvcF9JRC4KYGBge3J9CgojIFZpZXcodGFpbChBbGxEYXlzX05ld09yZGVyLCA1MDApKQoKQWxsRGF5c19OZXdUcmF2ZWxEaXN0IDwtIAogIG11dGF0ZShBbGxEYXlzX05ld09yZGVyLAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgPSBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWkgPCBURF9NaV9TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiBURF9NaV9TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnRfRiA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWkgPCBURF9NaV9TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiBURF9NaV9TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250X0YgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxEaXN0YW5jZV9NaSA8IFREX01pX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSA+IFREX01pX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250ID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyAhPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyA9PSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKSkpLAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdfTGFiZWwgPSAKICAgICAgICAgICBmYWN0b3IoaWZlbHNlKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWkgPCBURF9NaV9TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiBURF9NaV9TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnRfRiA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJURF9NaV9TU0hHX01lYW5fRiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbERpc3RhbmNlX01pIDwgVERfTWlfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gVERfTWlfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfQ250X0YgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX0NudF9GID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgIlREX01pX1NTX01lYW5fRiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbERpc3RhbmNlX01pIDwgVERfTWlfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gVERfTWlfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX0NudF9GIDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19DbnQgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAiVERfTWlfU1NfTWVhbiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZShpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgIT0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzIiwKICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyA9PSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgIlREX01pX1NTX01lYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgIlRyYXZlbERpc3RhbmNlX01pIgogICAgICAgICAgICAgICAgICAgICAgICApKSkpKQogICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMgPSBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pX0h2cnMpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgIT0gMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWlfTmV3IDwgVERfTWlfcTIgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3ID4gVERfTWlfcTk4CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzX0xhYmVsID0KICAgICAgICAgICBmYWN0b3IoaWZlbHNlKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgIT0gMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgPCBURF9NaV9xMiB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA+IFREX01pX3E5OAogICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgIlRyYXZlbERpc3RhbmNlX01pX0h2cnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKFRyYXZlbERpc3RhbmNlX01pX05ld19MYWJlbCkKICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICkKICAgICAgICApCgpzdHIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0KQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgJiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcuCgpRdWljayBzdW1tYXJ5IGFuZCB0aGVuIGNvcnJlbGF0aW9uIGNhbGN1bGF0aW9uLgpgYGB7cn0KCnJtKEFsbERheXNfTmV3T3JkZXIpCgoKIyAzOCByb3dzIG1lZXQgdGhpcyBjcml0ZXJpYSBhbnltb3JlICAtLSAgYXBwZWFycyB0byBiZSB0aGUgY2FzZSB3aGVuIGJvdGggdGhlIExhdCBMb25nIGNhbGN1bGF0aW9ucywgYW5kIHRoZSBUcmF2ZWxEaXN0YW5jZSBjYWxjdWxhdGlvbnMgZGlkIG5vdCBmdW5jdGlvbiBwcm9wZXJseS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICBpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpICYKICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICkKICAgICkKClZpZXcoQWxsRGF5c19OZXdUcmF2ZWxEaXN0ICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpKSAlPiUgCiAgICAgICBoZWFkKDUwMCkKICAgICkKCnN1bW1hcnkoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICkKICAgICAgICkKCnN1bW1hcnkoc2VsZWN0KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzCiAgICAgICAgICAgICAgKQogICAgICAgKQoKCmNvcihzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LAogICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKICAgICAgICAgICksCiAgICB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIgogICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZyc19MYWJlbCAmIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnNfTGFiZWwuCgpTaG93IGhvdyB0aGUgbGFiZWxzIGNoYW5nZWQuCmBgYHtyfQoKZ3JvdXBfYnkoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdfTGFiZWwsCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnNfTGFiZWwKICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoQ250TnVtID0gbigpLAogICAgICAgICAgICBDbnRQY3QgPSBmb3JtYXQoQ250TnVtIC8gbnJvdyhBbGxEYXlzX05ld1RyYXZlbERpc3QpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NpZW50aWZpYyA9IDk5OTkKICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICkgJT4lIAogIGFycmFuZ2UoZGVzYyhDbnRQY3QpCiAgICAgICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzICYgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LgoKR3JhcGhpbmcgdGhlIHR3byBtZXRob2RzIG9mIGNhbGN1bGF0aW5nIFRyYXZlbERpc3RhbmNlX01pLgoKRmlyc3QsIGxldCdzIGdldCBjcmVhdGUgYSBmdW5jdGlvbiB0byBwbG90IHRoZSBsaW5lciBtb2RlbCBlcXVhdGlvbi4KYGBge3J9CgpsbV9lcW4gPC0gZnVuY3Rpb24oZGYsIHksIHgpewogIG0gPC0gbG0oeSB+IHgsIGRmKQogIAogIGwgPC0gbGlzdChhID0gZm9ybWF0KGNvZWYobSlbMV0sIGRpZ2l0cyA9IDIpLAogICAgICAgICAgICBiID0gZm9ybWF0KGFicyhjb2VmKG0pWzJdKSwgZGlnaXRzID0gMiksCiAgICAgICAgICAgIHMxID0gaWZlbHNlKHRlc3QgPSBjb2VmKG0pWzJdID4gMCwKICAgICAgICAgICAgICAgICAgICAgICAgeWVzID0gIisiLAogICAgICAgICAgICAgICAgICAgICAgICBubyA9ICItIgogICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIHIyID0gZm9ybWF0KHN1bW1hcnkobSkkci5zcXVhcmVkLAogICAgICAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAzCiAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICkKICAKICBlcSA8LSBzdWJzdGl0dXRlKGl0YWxpYyh5KSA9PSBhfn5zMX5+YiAlLiUgaXRhbGljKHgpKiIsIn5+aXRhbGljKHIpXjJ+Ij0ifnIyLAogICAgICAgICAgICAgICAgICAgbAogICAgICAgICAgICAgICAgICApCiAgCiAgYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpCiAgICAgICAgICAgICAgKSAgICAgICAgICAgICAKfQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMuCgpTY2F0dGVyIHBsb3QgKHVzaW5nIGEgMTAlIHNhbXBsZSB0byBtYWtpbmcgcGxvdHRpbmcgdGltZSBmYXN0ZXIgYW5kIHRvIHJlZHVjZSB1bi1uZWVkZWQgZGF0YSBpbiB0aGUgInNhbWUiIHNwbG90KS4KYGBge3J9CgpzZXQuc2VlZCgxMjM0NTY3ODkpCkFsbERheXNfTmV3VHJhdmVsRGlzdF8xMFBjdCA8LSBmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICByZW5hbWUoRGlzdE1ldGhvZCA9IFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnNfTGFiZWwpICU+JSAKICBzYW1wbGVfZnJhYygwLjEpCgoKVHJhdkRpc3RfTWlWc0NhbGMgPC0gZ2dwbG90KHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3RfMTBQY3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEaXN0TWV0aG9kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBEaXN0TWV0aG9kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygicmVkIiwiYmx1ZSIsICJncmVlbiIsICJvcmFuZ2UiLCAiYmxhY2siKQogICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV9zaGFwZShzb2xpZCA9IEZBTFNFKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3VyID0gImJsdWUiKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvdXIgPSAicmVkIikgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAxLjUpLCB5bGltID0gYygwLCAxLjUpCiAgICAgICAgICAgICAgICAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxLjUsIDAuMjUpCiAgICAgICAgICAgICAgICAgICAgKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxLjUsIDAuMjUpCiAgICAgICAgICAgICAgICAgICAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsICNjKDAuODUsIDAuNDApLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KQogICAgICAgKSArCiAgYW5ub3RhdGUobGFiZWwgPSBsbV9lcW4oZGYgPSBBbGxEYXlzX05ld1RyYXZlbERpc3RfMTBQY3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IEFsbERheXNfTmV3VHJhdmVsRGlzdF8xMFBjdCRUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdUcmF2ZWxEaXN0XzEwUGN0JFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIyB4ID0gNjIsCiAgICAgICAgICAgIyB5ID0gMjAsCiAgICAgICAgICAgeCA9IDAuNzAsCiAgICAgICAgICAgeSA9IDAuMDAsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAiYmx1ZSIsCiAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICBhbm5vdGF0ZShsYWJlbCA9ICJSZWZlcmVuY2UgTGluZSAoc2xvcGUgPSAxKSIsCiAgICAgICAgICAgIyB4ID0gMTYsCiAgICAgICAgICAgIyB5ID0gMzAsCiAgICAgICAgICAgeCA9IDAuODAsCiAgICAgICAgICAgeSA9IDEuMDUsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAicmVkIgogICAgICAgICAgKSArCiAgbGFicyh0aXRsZSA9ICJUcmF2ZWxEaXN0YW5jZV9NaSB2cy4gVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyIsCiAgICAgICB4ID0gIlRyYXZlbERpc3RhbmNlX01pIiwKICAgICAgIHkgPSAiVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyIKICAgICAgKQojICsKIyAgIGdlb21faml0dGVyKCkKClRyYXZEaXN0X01pVnNDYWxjCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyAmIFRyYXZlbERpc3RhbmNlX01pX05ldy4KCkdyYXBoaW5nIHRlc3Qgd2l0aCByYm9rZWguCmBgYHtyfQoKVHJhdkRpc3RfTWlWc0NhbGNfQm9rZWggPC0gZmlndXJlKGRhdGEgPSBzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0XzEwUGN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlzdE1ldGhvZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bGltID0gYygwLCAxLjUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWxpbSA9IGMoMCwgMS41KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZF9sb2NhdGlvbiA9ICJib3R0b21fcmlnaHQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIGx5X3BvaW50cyh4ID0gVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgIHkgPSBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzLAogICAgICAgICAgICBjb2xvciA9IERpc3RNZXRob2QsCiAgICAgICAgICAgIGhvdmVyID0gYyhUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzLCBUcmF2ZWxEaXN0YW5jZV9NaSwgRGlzdE1ldGhvZCkKICAgICAgICAgICApICU+JSAKICBseV9hYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2xvciA9ICJyZWQiKQoKVHJhdkRpc3RfTWlWc0NhbGNfQm9rZWgKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LgoKfjExJSBvZiByaWRlcyBhcmUgc3RpbGwgc2hvd2luZyBhcyBsZXNzIHRoYW4gMC4xIG1pbGVzIG9mIFRyYXZlbERpc3RhbmNlX01pX05ldy4KYGBge3J9CgpybShUcmF2RGlzdF9NaVZzQ2FsY19Cb2tlaCkKcm0oQWxsRGF5c19OZXdUcmF2ZWxEaXN0XzEwUGN0KQoKCnN1bW1hcnkoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICkKICAgICAgICkKCnN1bW1hcnkoc2VsZWN0KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzCiAgICAgICAgICAgICAgKQogICAgICAgKQoKClRyYXZEaXN0TWlOZXdfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdfTGFiZWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZyc19MYWJlbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoIyBQY3RpbGUgPSBudGlsZShBbGxEYXlzX05ld1RyYXZlbERpc3QkVHJhdmVsRGlzdGFuY2VfTWlfTmV3LCAxMDApLAogICAgICAgICAjIE1pblIgPSBtaW5fcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkVHJhdmVsRGlzdGFuY2VfTWlfTmV3KSwKICAgICAgICAgUGN0Ul9OID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpLAogICAgICAgICBQY3RSX0ggPSBwZXJjZW50X3JhbmsoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMpLAogICAgICAgICBQY3RSX1JvdW5kX04gPSByb3VuZChQY3RSX04sIDIpLAogICAgICAgICBQY3RSX1JvdW5kX0ggPSByb3VuZChQY3RSX0gsIDIpCiAgICAgICAgKSAKCiMgY29sbmFtZXMoVHJhdkRpc3RNaU5ld19OdGlsZSlbMV0gPC0gIlRyYXZlbERpc3RhbmNlX01pX05ldyIKIyBzdHIoVHJhdkRpc3RNaU5ld19OdGlsZSkKVmlldyhoZWFkKFRyYXZEaXN0TWlOZXdfTnRpbGUsIDUwMCkpCgpUcmF2RGlzdE1pTmV3X050aWxlX1Jvd3MgPC0gbnJvdyhUcmF2RGlzdE1pTmV3X050aWxlKQoKIyBWaWV3KHRhaWwoVHJhdkRpc3RNaU5ld19OdGlsZSwgNTAwKSkKCgpUcmF2RGlzdE1pTmV3X1BjdGlsZXMgPC0gZ3JvdXBfYnkoVHJhdkRpc3RNaU5ld19OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmRfSAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5URE1pQXRQY3RpbGVfTiA9IG1pbihUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpLAogICAgTWluVERNaUF0UGN0aWxlX0ggPSBtaW4oVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyksCiAgICBDbnRzQXRQY3RpbGVfTiA9IHN1bSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3KSksCiAgICBDbnRzQXRQY3RpbGVfSCA9IHN1bSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycykpLAogICAgUGN0c0F0UGN0aWxlX04gPSBDbnRzQXRQY3RpbGVfTiAvIFRyYXZEaXN0TWlOZXdfTnRpbGVfUm93cywKICAgIFBjdHNBdFBjdGlsZV9IID0gQ250c0F0UGN0aWxlX0ggLyBUcmF2RGlzdE1pTmV3X050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UF9OID0gY3Vtc3VtKFBjdHNBdFBjdGlsZV9OKSwKICAgICAgICAgQ3VtU3VtUEF0UF9IID0gY3Vtc3VtKFBjdHNBdFBjdGlsZV9IKQogICAgICAgICkKClZpZXcoVHJhdkRpc3RNaU5ld19QY3RpbGVzKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcuCgpXaHkgYXJlIHRoZXJlIHN0aWxsIHNvbWUgc21hbGwgb3IgemVybyBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgdmFsdWVzLgpgYGB7cn0KCnJtKFRyYXZEaXN0TWlOZXdfTnRpbGUpCnJtKFRyYXZEaXN0TWlOZXdfTnRpbGVfUm93cykKCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKFRyYXZlbERpc3RhbmNlX01pX05ldykgJT4lIAogICAgICAgaGVhZCg1MDApCiAgICApCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKFRyYXZlbERpc3RhbmNlX01pX05ldykgJT4lIAogICAgICAgdGFpbCg1MDApCiAgICApCgoKCgpmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3KQogICAgICAgKSAlPiUgCiAgZ3JvdXBfYnkoVHJhdmVsRGlzdGFuY2VfTWlfTmV3X0xhYmVsKSAlPiUgCiAgc3VtbWFyaXNlKENudE51bSA9IG4oKQogICAgICAgICAgICAjICwKICAgICAgICAgICAgIyBDbnRQY3QgPSBuKCkgLyBucm93KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3KQogICAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgKQoKICAgICAgCiAgICAgIAojIGV4YW1wbGVzIG9mIFRyYXZlbERpc3RhbmNlX01pX05ldyB2YWx1ZXMgdGhhdCBhcmUgemVyby4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDE2NTIgJiBSb3dOdW1fT0cgPD0gMTY3MikgfCAjIDE2NjIgIC0tICAxc3QgdHJpcCBvZiBhIG5ldyByb3V0ZSAmIG5vIGNoYW5nZSBpbiBsYXQgbG9uCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDkyMzc4ICYgUm93TnVtX09HIDw9IDkyMzk4KSB8ICMgOTIzODggIC0tICBvZG9tZXRlciBhbHdheXMgYXQgemVybyAmIG5vIGNoYW5nZSBpbiBsYXQgbG9uCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDE0NDc0NjIgJiBSb3dOdW1fT0cgPD0gMTQ0NzQ4MikgfCAjIDE0NDc0NzIgIC0tICBubyBjaGFuZ2UgaW4gb2RvbWV0ZXIgJiBubyBjaGFuZ2UgaW4gbGF0IGxvbgogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNDg1ODQ1ICYgUm93TnVtX09HIDw9IDE0ODU4NjUpICMgMTQ4NTg1NSAgLS0gIG5vIGNoYW5nZSBpbiBvZG9tZXRlciAmIG5vIGNoYW5nZSBpbiBsYXQgbG9uCiAgICAgICAgICAgKQogICAgKQoKClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3ID4gMCAmCiAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3IDwgMC4wOTg0ODQ4NDg1ICYgICMgMC4wOTg0ODQ4NDg1IGlzIGFuIE1EQVQgZ3Vlc3MgYXQgYSBkaXN0YW5jZSBiZXR3ZWVuIHN0b3BzCiAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfRnQgPT0gMCAgIyBtZWFuaW5nIFRyYXZlbERpc3RhbmNlX01pX05ldyBpcyBiYXNlZCBvbiBIYXZlcnNpbmUgZGlzdGFuY2UgKGxhdCBsb25nIHZhbHVlcykKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoVHJhdmVsRGlzdGFuY2VfTWlfTmV3KQogICAgKQoKIyBleGFtcGxlcyBvZiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgdmFsdWVzIHRoYXQgYXJlIHZlcnkgc21hbGwuIEFsbCBhcmUgZXhhbXBsZXMgb2Ygbm8gY2hhbmdlIGluIHRoZSBvZG9tZXRlciwgYW5kIGV4dHJlbWVseSBzbWFsbCBjaGFuZ2VzIGluIGxhdCBsb24uClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgKFJvd051bV9PRyA+PSA5MjEwMzYgJiBSb3dOdW1fT0cgPD0gOTIxMDU2KSB8ICMgOTIxMDQ2ICAtLSAgCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDIyODEyMzUgJiBSb3dOdW1fT0cgPD0gMjI4MTI1NSkgfCAjIDIyODEyNDUgIC0tICAKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjk1NjUyOCAmIFJvd051bV9PRyA8PSAyOTU2NTQ4KSB8ICMgMjk1NjUzOCAgLS0gIAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyOTA5MDA3ICYgUm93TnVtX09HIDw9IDI5MDkwMjcpICMgMjkwOTAxNyAgLS0gIAogICAgICAgICAgICkKICAgICkKCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA+IDAgJgogICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA8IDAuMDk4NDg0ODQ4NSAmICAjIDAuMDk4NDg0ODQ4NSBpcyBhbiBNREFUIGd1ZXNzIGF0IGEgZGlzdGFuY2UgYmV0d2VlbiBzdG9wcwogICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX0Z0ICE9IDAgICMgbWVhbmluZyBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgaXMgYmFzZWQgb24gYWN0dWFsIG9kb21ldGVyIHJlYWRpbmdzCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKFRyYXZlbERpc3RhbmNlX01pX05ldykKICAgICkKCiMgZXhhbXBsZXMgb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3IHZhbHVlcyB0aGF0IGFyZSB2ZXJ5IHNtYWxsLiBBbGwgYXJlIGV4YW1wbGVzIG9mIGV4dHJlbWVseSBzbWFsbCBjaGFuZ2VzIGluIHRoZSBvZG9tZXRlci4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDE2ODEgJiBSb3dOdW1fT0cgPD0gMTcwMSkgfCAjIDE2OTEgIC0tICAKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjEzMSAmIFJvd051bV9PRyA8PSAyMTUxKSB8ICMgMjE0MSAgLS0gIAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNTQ3ODQgJiBSb3dOdW1fT0cgPD0gMTU0ODA0KSB8ICMgMTU0Nzk0ICAtLSAgCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDIyNjc0MzEgJiBSb3dOdW1fT0cgPD0gMjI2NzQ1MSkgIyAyMjY3NDQxICAtLSAgCiAgICAgICAgICAgKQogICAgKQoKYGBgCgoKRXhwbG9yZSBpbnN0YW5jZXMgd2hlcmUgVHJhdmVsRGlzdGFuY2VfTWkgaXMgTkEuCmBgYHtyfQoKVmlldyhncm91cF9ieShBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRAogICAgICAgICAgICAgKSAlPiUgCiAgICAgICBzdW1tYXJpc2UoQ250cyA9IHN1bShpcy5uYShUcmF2ZWxUaW1lX1NlYykKICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoQ250cykKICAgICAgICAgICAgICApCiAgICApCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBTdGFydFN0b3BfSUQgPT0gIjUwMDQ2MzUtLTUwMDQ3NTgiCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBzZWxlY3QoVHJhdmVsVGltZV9TZWMsCiAgICAgICAgICAgICAgVFRfU2VjX1NTX01lYW4sCiAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfTWVhbiwKICAgICAgICAgICAgICBUVF9TZWNfU1NfTWVkLAogICAgICAgICAgICAgIFRUX1NlY19TU0hHX01lZCwKICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250LAogICAgICAgICAgICAgIFRUX1NlY19TU0hHX0NudAogICAgICAgICAgICAgICkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsVGltZV9Ici4KClZpZXcoVHJhdkRpc3RNaV9QY3RpbGVzKTogOTglIG9mIFRyYXZlbFRpbWVfSHIgYXJlIGJldHdlZW4gNyBzZWNvbmRzIGFuZCA0NjQgc2Vjb25kcyAofjggbWludXRlcykuCmBgYHtyfQoKVHJhdlRpbWVIcl9OdGlsZSA8LSBhcy5kYXRhLmZyYW1lKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxUaW1lX0hyKSAlPiUgCiAgbXV0YXRlKFBjdGlsZSA9IG50aWxlKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxUaW1lX0hyLCAxMDApLAogICAgICAgICBNaW5SID0gbWluX3JhbmsoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFRyYXZlbFRpbWVfSHIpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxUaW1lX0hyKSwKICAgICAgICAgUGN0Ul9Sb3VuZCA9IHJvdW5kKFBjdFIsIDIpCiAgICAgICAgKSAKCmNvbG5hbWVzKFRyYXZUaW1lSHJfTnRpbGUpWzFdIDwtICJUcmF2ZWxUaW1lX0hyIgpzdHIoVHJhdlRpbWVIcl9OdGlsZSkKClRyYXZUaW1lSHJfTnRpbGVfUm93cyA8LSBucm93KFRyYXZUaW1lSHJfTnRpbGUpCgpWaWV3KHRhaWwoVHJhdlRpbWVIcl9OdGlsZSwgNTAwKSkKCgpUcmF2VGltZUhyX1BjdGlsZXMgPC0gZ3JvdXBfYnkoVHJhdlRpbWVIcl9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgTWluVHJhdlRpbWVIckF0UGN0aWxlID0gbWluKFRyYXZlbFRpbWVfSHIpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gVHJhdlRpbWVIcl9OdGlsZV9Sb3dzCiAgKSAlPiUgCiAgbXV0YXRlKEN1bVN1bVBBdFAgPSBjdW1zdW0oUGN0c0F0UGN0aWxlKSwKICAgICAgICAgTWluVHJhdlRpbWVTZWNBdFBjdGlsZSA9IE1pblRyYXZUaW1lSHJBdFBjdGlsZSAqIDM2MDAKICAgICAgICApCgpWaWV3KFRyYXZUaW1lSHJfUGN0aWxlcykKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsVGltZV9Ici4KCkhpc3RvZ3JhbSBvZiBUcmF2ZWxUaW1lX1NlYy4KYGBge3J9CgpUcmF2VGltZV9TZWNfSGlzdERlbiA8LSBnZ3Bsb3QoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEoVHJhdmVsVGltZV9TZWMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBUcmF2ZWxUaW1lX1NlYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gLi5kZW5zaXR5Li4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3VyID0gImdyZXk2MCIsIHNpemUgPSAwLjIpICsKICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgY29sb3VyID0gInJlZCIpICsKICAjIHN0YXRfYmluKGJpbndpZHRoID0gNSwKICAjICAgICAgICAgIGdlb20gPSAidGV4dCIsCiAgIyAgICAgICAgICBzaXplID0gMi41LAogICMgICAgICAgICAgdmp1c3QgPSAxLjUsCiAgIyAgICAgICAgICBhZXMobGFiZWwgPSBmb3JtYXQoLi5jb3VudC4uLCBiaWcubWFyayA9ICIsIikKICAjICAgICAgICAgICAgICksCiAgIyAgICAgICAgICkgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAxODApLCB5bGltID0gYygwLCAwLjAyKQogICAgICAgICAgICAgICAgICkgKwogICMgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBsYWJzKHRpdGxlID0gIlZhcmlhdGlvbiBpbiBUcmF2ZWwgVGltZSIsCiAgICAgICB4ID0gIlRyYXZlbCBUaW1lIChzZWMpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIKICAgICAgKQoKVHJhdlRpbWVfU2VjX0hpc3REZW4KCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsVGltZV9Ici4KCkxvb2tpbmcgYXQgb2RkIFRyYXZlbFRpbWVfU2VjIHZhbHVlcy4KYGBge3J9CgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIGlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmIAogICAgICAgICAgICAgICFpcy5uYShPZG9tZXRlcl9EaXN0YW5jZV9MYWcxKQogICAgICAgICAgICkKICAgICkKCgojIGV4YW1wbGVzIG9mIFRyYXZlbFRpbWVfU2VjIHZhbHVlcyB0aGF0IGFyZSBOQS4gVGhlc2UgYXJlIE5BIGJlY2F1c2UgdGhlIEV2ZW50X1RpbWUgJiBEZXBhcnR1cmVfVGltZSByZWFkaW5ncyBhcmUgbm90IGFjY3VyYXRlIChpLmUuLCB0aGUgcHJldmlvdXMgRGVwYXJ0dXJlX1RpbWUgaXMgQkVGT1JFIHRoZSBjdXJyZW50IEV2ZW50X1RpbWUpLgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gOTA4MDkgJiBSb3dOdW1fT0cgPD0gOTA4MjkpIHwgIyA5MDgxOQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA5MDg4MSAmIFJvd051bV9PRyA8PSA5MDkwMSkgfCAjIDkwODkxCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDk5NDgxMyAmIFJvd051bV9PRyA8PSA5OTQ4MzMpIHwgIyA5OTQ4MjMKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjM5MTM0MiAmIFJvd051bV9PRyA8PSAyMzkxMzYyKSAjIDIzOTEzNTIKICAgICAgICAgICApCiAgICApCgoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA9PSAwCiAgICAgICAgICAgKQogICAgKQoKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyB6ZXJvIChpLmUuLCBwcmV2aW91cyBEZXBhcnR1cmVfVGltZSBlcXVhbHMgdGhlIGN1cnJlbnQgRXZlbnRfVGltZSkuClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNzU3MjUgJiBSb3dOdW1fT0cgPD0gMTc1NzQ1KSB8ICMgMTc1NzM1CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDQwMTEyNyAmIFJvd051bV9PRyA8PSA0MDExNDcpIHwgIyA0MDExMzcKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjQ0NjgyMCAmIFJvd051bV9PRyA8PSAyNDQ2ODQwKSB8ICMgMjQ0NjgzMAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyNTQ1MDM2ICYgUm93TnVtX09HIDw9IDI1NDUwNTYpICMgMjU0NTA0NgogICAgICAgICAgICkKICAgICkKCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gMCAmCiAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPCAxMAogICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShkZXNjKFNwZWVkQXZnX01waCkKICAgICAgICAgICAgICApCiAgICApCgoKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyB1bnVzdWFsbHkgc21hbGwgKHdpdGggVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIHRoYXQgYXJlIGxhcmdlKS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDEwNDIyMjggJiBSb3dOdW1fT0cgPD0gMTA0MjI0OCkgfCAjIDEwNDIyMzgKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNTM4MTYgJiBSb3dOdW1fT0cgPD0gNTM4MzYpIHwgIyA1MzgyNgogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzNjA1NzEgJiBSb3dOdW1fT0cgPD0gMzYwNTkxKSB8ICMgMzYwNTgxCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDUwMjI3MSAmIFJvd051bV9PRyA8PSA1MDIyOTEpICMgNTAyMjgxIChjYW4ndCBleHBsaWFuIHRoZSB3ZWlyZCBUcmF2ZWxUaW1lX1NlYyBjYWxjdWxhdGlvbiBoZXJlIC0gaXQncyBub3QgZXZlbiBhbiBpbnRlZ2VyISkKICAgICAgICAgICApCiAgICApCgojIHN0aWxsIHRyeWluZyB0byBleHBsYWluIDUwMjI4MS4uLm9uIHRoZSBkYXkgb2YgdGhpcyB3ZWlyZG5lc3MsIHRoZSBidXMgd2FzIG9ubHkgaW4gY2lyY3VsYXRpb24gZm9yIDQtNSBzdG9wcyAofjIwIG1pbnV0ZXMpIG9uIHRoYXQgZGF5IChPY3QgNikKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICBCdXNfSUQgPT0gMjcxMQogICAgICAgICAgICkKICAgICkKCgojIGV4cGxvcmluZyBsYXJnZSB2YWx1ZXMgZm9yIFRyYXZlbFRpbWVfU2VjClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPT0gMzAwCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsVGltZV9TZWMpLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyCiAgICAgICAgICAgICAgKQogICAgKQoKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyB1bnVzdWFsbHkgbGFyZ2UgKHdpdGggVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIHRoYXQgYXJlIHNtYWxsLCBzbyBTcGVlZEF2Z19NcGggdmFsdWVzIGFyZSB2ZXJ5IHNtYWxsKS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDI2Mjc0NTkgJiBSb3dOdW1fT0cgPD0gMjYyNzQ3OSkgfCAjIDI2Mjc0NjkKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjE5MzM0NCAmIFJvd051bV9PRyA8PSAyMTkzMzY0KSB8ICMgMjE5MzM1NAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNjQ0MTIzICYgUm93TnVtX09HIDw9IDE2NDQxNDMpIHwgIyAxNjQ0MTMzCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDg2OTYwMCAmIFJvd051bV9PRyA8PSA4Njk2MjApICMgODY5NjEwCiAgICAgICAgICAgKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyCgpWaWV3KFNwZWVkX1BjdGlsZXMpOiA5MCUgb2YgU3BlZWRBdmdfTXBoMiBhcmUgYmV0d2VlbiB+M21waCBhbmQgfjY2bXBoLgpgYGB7cn0KClNwZWVkX050aWxlIDwtIGFzLmRhdGEuZnJhbWUoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFNwZWVkQXZnX01waDIpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFNwZWVkQXZnX01waDIsIDEwMCksCiAgICAgICAgIE1pblIgPSBtaW5fcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkU3BlZWRBdmdfTXBoMiksCiAgICAgICAgIFBjdFIgPSBwZXJjZW50X3JhbmsoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFNwZWVkQXZnX01waDIpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoU3BlZWRfTnRpbGUpWzFdIDwtICJTcGVlZEF2Z19NcGgyIgpzdHIoU3BlZWRfTnRpbGUpCgpTcGVlZF9OdGlsZV9Sb3dzIDwtIG5yb3coU3BlZWRfTnRpbGUpCgpWaWV3KHRhaWwoU3BlZWRfTnRpbGUsIDUwMCkpCgoKU3BlZWRfUGN0aWxlcyA8LSBncm91cF9ieShTcGVlZF9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5TcGVlZEF0UGN0aWxlID0gbWluKFNwZWVkQXZnX01waDIpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gU3BlZWRfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSkKICAgICAgICApCgpWaWV3KFNwZWVkX1BjdGlsZXMpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwZWVkQXZnX01waDIuCgpFeHBsb3JpbmcgdGhlIHJlbW92YWwgb2Ygb3V0bGllciBUcmF2ZWxUaW1lX1NlYyBhbmQgVHJhdmVsRGlzdGFuY2VfTWkuCmBgYHtyfQoKc3VtbWFyeShzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgsCiAgICAgICAgICAgICAgIFNwZWVkQXZnX01waDIKICAgICAgICAgICAgICApCiAgICAgICApCgpzdW1tYXJ5KHNlbGVjdChmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiAwLjAwMDE4OTM5MzkgJiAjIGxvd2VzdCBub24temVybyBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pIDwgMS4wODEyNTAwMDAwICYgIyA5OXRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiAxMC4wNTAwMDAgJiAjIDJuZCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjIDwgMjkzLjAwMDAwMCAjIDk4dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgsCiAgICAgICAgICAgICAgIFNwZWVkQXZnX01waDIKICAgICAgICAgICAgICApCiAgICAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwZWVkQXZnX01waDIuCgpIaXN0b2dyYW0gb2YgU3BlZWRBdmdfTXBoMi4KYGBge3J9CgpTcGVlZF9IaXN0RGVuIDwtIGdncGxvdChmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKFNwZWVkQXZnX01waDIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gU3BlZWRBdmdfTXBoMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAuLmRlbnNpdHkuLgogICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG91ciA9ICJncmV5NjAiLCBzaXplID0gMC4yKSArCiAgZ2VvbV9saW5lKHN0YXQgPSAiZGVuc2l0eSIsIGNvbG91ciA9ICJyZWQiKSArCiAgc3RhdF9iaW4oYmlud2lkdGggPSA1LAogICAgICAgICAgIGdlb20gPSAidGV4dCIsCiAgICAgICAgICAgc2l6ZSA9IDIuNSwKICAgICAgICAgICB2anVzdCA9IDEuNSwKICAgICAgICAgICBhZXMobGFiZWwgPSBmb3JtYXQoLi5jb3VudC4uLCBiaWcubWFyayA9ICIsIikKICAgICAgICAgICAgICApLAogICAgICAgICAgKSArCiAgIyBnZW9tX3RleHQoYWVzKGxhYmVsID0gZm9ybWF0KC4uY291bnQuLiwgYmlnLm1hcmsgPSAiLCIpCiAgIyAgICAgICAgICAgICAgKSwKICAjICAgICAgICAgICBzaXplID0gMywKICAjICAgICAgICAgICBudWRnZV95ID0gKC4uY291bnQuLiAqIDAuMSkKICAjICAgICAgICAgICkgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCA3MCksIHlsaW0gPSBjKDAsIDAuMDQpCiAgICAgICAgICAgICAgICAgKSArCiAgIyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIGxhYnModGl0bGUgPSAiVmFyaWF0aW9uIGluIFRyYXZlbCBTcGVlZCIsCiAgICAgICB4ID0gIkF2ZXJhZ2UgU3BlZWQgKG1waCkiLAogICAgICAgeSA9ICJEZW5zaXR5IgogICAgICApCgpTcGVlZF9IaXN0RGVuCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwZWVkQXZnX01waDIuCgpIaXN0b2dyYW0gb2YgU3BlZWRBdmdfTXBoMiBhZnRlciByZW1vdmluZyBvdXRsaWVyIFRyYXZlbFRpbWVfU2VjIGFuZCBUcmF2ZWxEaXN0YW5jZV9NaS4KYGBge3J9CgpWaWV3KFRyYXZEaXN0TWlOZXdfUGN0aWxlcykKVmlldyhUcmF2VGltZUhyX1BjdGlsZXMpCgpTcGVlZE5vT3V0bGllcl9IaXN0RGVuIDwtIGdncGxvdChmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKFNwZWVkQXZnX01waDIpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3ID4gMC4wNzc4NDEwMDUgJiAjIDV0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWlfTmV3IDwgMS4wODEyNTAwMDAwICYgIyA5OXRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiAxMi4xMDAwMDAgIyA0dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbFRpbWVfU2VjIDwgMjkzLjAwMDAwMCAjIDk4dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFNwZWVkQXZnX01waDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gLi5kZW5zaXR5Li4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvdXIgPSAiZ3JleTYwIiwgc2l6ZSA9IDAuMikgKwogIGdlb21fbGluZShzdGF0ID0gImRlbnNpdHkiLCBjb2xvdXIgPSAicmVkIikgKwogIHN0YXRfYmluKGJpbndpZHRoID0gNSwKICAgICAgICAgICBnZW9tID0gInRleHQiLAogICAgICAgICAgIHNpemUgPSAyLjUsCiAgICAgICAgICAgdmp1c3QgPSAxLjUsCiAgICAgICAgICAgYWVzKGxhYmVsID0gZm9ybWF0KC4uY291bnQuLiwgYmlnLm1hcmsgPSAiLCIpCiAgICAgICAgICAgICAgKSwKICAgICAgICAgICkgKwogICMgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGZvcm1hdCguLmNvdW50Li4sIGJpZy5tYXJrID0gIiwiKQogICMgICAgICAgICAgICAgICksCiAgIyAgICAgICAgICAgc2l6ZSA9IDMsCiAgIyAgICAgICAgICAgbnVkZ2VfeSA9ICguLmNvdW50Li4gKiAwLjEpCiAgIyAgICAgICAgICApICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgNzApLCB5bGltID0gYygwLCAwLjA0KQogICAgICAgICAgICAgICAgICkgKwogICMgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBsYWJzKHRpdGxlID0gIlZhcmlhdGlvbiBpbiBUcmF2ZWwgU3BlZWQiLAogICAgICAgc3VidGl0bGUgPSAiKHJlbW92ZWQgbG93IG91dGxpZXJzIG9mIFRyYXZlbCBEaXN0YW5jZSBhbmQgVHJhdmVsIFRpbWUpIiwKICAgICAgIHggPSAiQXZlcmFnZSBTcGVlZCAobXBoKSIsCiAgICAgICB5ID0gIkRlbnNpdHkiCiAgICAgICkKClNwZWVkTm9PdXRsaWVyX0hpc3REZW4KCmBgYAoKCkludmVzdGlnYXRpb24gb2YgU3BlZWRBdmdfTXBoMi4KCk5ldyBkYXRhc2V0IChOb091dGxpZXJzX1RyYXZlbERpc3ROVGltZSkgd2hlbiByZW1vdmluZyBvdXRsaWVyIGxvdyB2YWx1ZXMgb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3IGFuZCBUcmF2ZWxUaW1lX1NlYy4KYGBge3J9CgpWaWV3KFRyYXZEaXN0TWlOZXdfUGN0aWxlcykKVmlldyhUcmF2VGltZUhyX1BjdGlsZXMpCgpOb091dGxpZXJzX1RyYXZlbERpc3ROVGltZSA8LSBmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3ID4gLjA3Nzg0MTAwNSAmICMgNXRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgPCAxLjA4MTI1MDAwMDAgJiAjIDk5dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA+IDEyLjEwMDAwMCAjIDR0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVHJhdmVsVGltZV9TZWMgPCAyOTMuMDAwMDAwICMgOTh0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCm5yb3coQWxsRGF5c19OZXdUcmF2ZWxEaXN0KSAtIG5yb3coTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUpCgpzdHIoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUpCnN1bW1hcnkoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwcGVkQXZnX01waDIuCgpWaWV3KFNwZWVkX05vT3V0X1BjdGlsZXMpOiAgQXByb3hpbWF0ZWx5IDkwJSBvZiBTcGVlZEF2Z19NcGgyIHZhbHVlcyBhcmUgYmV0d2VlbiB+NG1waCBhbmQgfjU2bXBoLgpgYGB7cn0KClNwZWVkX05vT3V0X050aWxlIDwtIGFzLmRhdGEuZnJhbWUoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUkU3BlZWRBdmdfTXBoMikgJT4lIAogIG11dGF0ZShQY3RpbGUgPSBudGlsZShOb091dGxpZXJzX1RyYXZlbERpc3ROVGltZSRTcGVlZEF2Z19NcGgyLCAxMDApLAogICAgICAgICBNaW5SID0gbWluX3JhbmsoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUkU3BlZWRBdmdfTXBoMiksCiAgICAgICAgIFBjdFIgPSBwZXJjZW50X3JhbmsoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUkU3BlZWRBdmdfTXBoMiksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkgCgpjb2xuYW1lcyhTcGVlZF9Ob091dF9OdGlsZSlbMV0gPC0gIlNwZWVkQXZnX01waDIiCnN0cihTcGVlZF9Ob091dF9OdGlsZSkKClNwZWVkX05vT3V0X050aWxlX1Jvd3MgPC0gbnJvdyhTcGVlZF9Ob091dF9OdGlsZSkKClZpZXcodGFpbChTcGVlZF9Ob091dF9OdGlsZSwgNTAwKSkKCgpTcGVlZF9Ob091dF9QY3RpbGVzIDwtIGdyb3VwX2J5KFNwZWVkX05vT3V0X050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblNwZWVkQXRQY3RpbGUgPSBtaW4oU3BlZWRBdmdfTXBoMiksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBTcGVlZF9Ob091dF9OdGlsZV9Sb3dzCiAgKSAlPiUgCiAgbXV0YXRlKEN1bVN1bVBBdFAgPSBjdW1zdW0oUGN0c0F0UGN0aWxlKQogICAgICAgICkKClZpZXcoU3BlZWRfTm9PdXRfUGN0aWxlcykKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgU3BwZWRBdmdfTXBoMi4KCkV4bG9yaW5nIG9kZC9pbXBvc3NpYmxlIHZhbHVlcy4KYGBge3J9CgojIEV4cGxvcmluZyB3aGVuIFNwZWVkQXZnX01waDIgaXMgTkEgIC0tICBkb2VzIG5vdCBvY2N1ciBhdCBhbGwKbnJvdyhmaWx0ZXIoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUsCiAgICAgICAgICAgIGlzLm5hKFNwZWVkQXZnX01waDIpCiAgICAgICAgICAgKQogICAgKQoKCiMgRXhwbG9yaW5nIHdoZW4gU3BlZWRBdmdfTXBoMiBpcyB6ZXJvICAtLSAgZG9lcyBub3Qgb2NjdXIgYXQgYWxsCm5yb3coZmlsdGVyKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lLAogICAgICAgICAgICBTcGVlZEF2Z19NcGgyID09IDAKICAgICAgICAgICApCiAgICApCgoKIyBleGFtcGxlcyB3aGVyZSBTcGVlZEF2Z19NcGgyIDwgMy4yODQ4NzcwClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgU3BlZWRBdmdfTXBoMiA+IDAgJgogICAgICAgICAgICAgIFNwZWVkQXZnX01waDIgPCAzLjI4NDg3NzAKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoU3BlZWRBdmdfTXBoMikKICAgICkKCiMgZXhhbXBsZXMgd2hlcmUgU3BlZWRBdmdfTXBoMiA8IDMuMjg0ODc3MApWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNDg1MzM4ICYgUm93TnVtX09HIDw9IDQ4NTM1OCkgfCAjIDQ4NTM0OCAgLS0gIEV4dHJlbWUgdHJhdmVsIHRpbWUsIFJvdXRlIENoYW5nZQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzNDY5NTIgJiBSb3dOdW1fT0cgPD0gMzQ2OTcyKSB8ICMgMzQ2OTYyICAtLSBFeHRyZW1lIHRyYXZlbCB0aW1lLCBSb3V0ZSBDaGFuZ2UgCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDcwNDk0ICYgUm93TnVtX09HIDw9IDcwNTE0KSB8ICMgNzA1MDQgIC0tICBFeHRyZW1lIHRyYXZlbCB0aW1lLCBSb3V0ZSBDaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjA1MTg0NiAmIFJvd051bV9PRyA8PSAyMDUxODY2KSAjIDIwNTE4NTYgIC0tICBFeHRyZW1lIHRyYXZlbCB0aW1lLCBSb3V0ZSBDaGFuZ2UKICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwZWVkQXZnX01waDIuCgpMaW1pdCB0aGUgZGF0YXNldCBiYXNlZCBvbiBTcGVlZEF2Z19NcGgyLgpgYGB7cn0KCk5vT3V0bGllcnNTcGVlZCA8LSBmaWx0ZXIoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYmV0d2VlbihTcGVlZEF2Z19NcGgyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgNC4wNjkzMDAsICMgNXRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDU2LjA1NjUxICM5NXRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICkKCm5yb3coTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUpIC0gbnJvdyhOb091dGxpZXJzU3BlZWQpCgpzdW1tYXJ5KE5vT3V0bGllcnNTcGVlZCkKCmBgYAoKClRyYXZlbFRpbWUgbm93IGxvb2tzIGxpa2UgaXQgaGFzIHNvbWUgb2RkIHZhbHVlcyBvbiB0aGUgaGlnaCBlbmQuICBTbyBsZXQncyBsb29rIGF0IHRob3NlLgoKVmlldyhUcmF2VGltZV9Ob091dF9QY3RpbGVzKTogIFZpcnR1YWxseSBhbGwgdHJpcHMgc2hvdWxkIHRha2UgbGVzcyB0aGFuIDUgbWludXRlcy4gKFRoZSA5OXRoIHBlcmNlbnRpbGUgb2Ygb2YgVHJhdmVsVGltZSBpcyBhcHByb3hpbWF0ZWx5IDggbWludXRlcy4pCmBgYHtyfQoKVHJhdlRpbWVfTm9PdXRfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShOb091dGxpZXJzU3BlZWQkVHJhdmVsVGltZV9IcikgJT4lIAogIG11dGF0ZShQY3RpbGUgPSBudGlsZShOb091dGxpZXJzU3BlZWQkVHJhdmVsVGltZV9IciwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKE5vT3V0bGllcnNTcGVlZCRUcmF2ZWxUaW1lX0hyKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhOb091dGxpZXJzU3BlZWQkVHJhdmVsVGltZV9IciksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkKCmNvbG5hbWVzKFRyYXZUaW1lX05vT3V0X050aWxlKVsxXSA8LSAiVHJhdmVsVGltZV9IciIKc3RyKFRyYXZUaW1lX05vT3V0X050aWxlKQoKVHJhdlRpbWVfTm9PdXRfTnRpbGVfUm93cyA8LSBucm93KFRyYXZUaW1lX05vT3V0X050aWxlKQoKVmlldyh0YWlsKFRyYXZUaW1lX05vT3V0X050aWxlLCA1MDApKQoKClRyYXZUaW1lX05vT3V0X1BjdGlsZXMgPC0gZ3JvdXBfYnkoVHJhdlRpbWVfTm9PdXRfTnRpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGN0Ul9Sb3VuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgTWluVHJhdlRpbWVIckF0UGN0aWxlID0gbWluKFRyYXZlbFRpbWVfSHIpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gVHJhdlRpbWVfTm9PdXRfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSksCiAgICAgICAgIE1pblRyYXZUaW1lU2VjQXRQY3RpbGUgPSBNaW5UcmF2VGltZUhyQXRQY3RpbGUgKiAoNjAgKiA2MCkKICAgICAgICApCgpWaWV3KFRyYXZUaW1lX05vT3V0X1BjdGlsZXMpCgpgYGAKCgpJbnZlc3RpZ2F0aW5nIG9kZCBUcmF2ZWxUaW1lX1NlYyB2YWx1ZXMuCgpUcmlwcyBsb25nZXIgdGhhbiB+OCBtaW51dGVzLgpgYGB7cn0KClZpZXcoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiA0OTEgIyBtaW4gYXQgdGhlIDEwMHRoIHBlcmNlbnRpbGUKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhUcmF2ZWxUaW1lX1NlYykKICAgICAgICAgICAgICApCiAgICApCgojIGV4YW1wbGVzIG9mIFRyYXZlbFRpbWVfU2VjIHZhbHVlcyB0aGF0IGFyZSBsYXJnZXN0LgpWaWV3KGZpbHRlcihOb091dGxpZXJzU3BlZWQsCiAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjA3MTc1OSAmIFJvd051bV9PRyA8PSAyMDcxNzc5KSB8ICMgMjA3MTc2OSAgLS0gIHJlc3VsdHMgZnJvbSBhIHJvdXRlIGNoYW5nZSwgYW5kIGEgM2hyKyB3YWl0IGJlZm9yZSB0aGUgbmV3IHJvdXRlIHN0YXJ0cwogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNDczNjg2ICYgUm93TnVtX09HIDw9IDE0NzM3MDYpIHwgIyAxNDczNjk2ICAtLSAgcmVzdWx0cyBmcm9tIGEgcm91dGUgY2hhbmdlLCBhbmQgYSAzaHIgd2FpdCBiZWZvcmUgdGhlIG5ldyByb3V0ZSBzdGFydHMKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTIyMjgyMiAmIFJvd051bV9PRyA8PSAxMjIyODQyKSB8ICMgMTIyMjgzMiAgLS0gIHJlc3VsdHMgZnJvbSBhIHJvdXRlIGNoYW5nZSwgYW5kIGEgM2hyIHdhaXQgYmVmb3JlIHRoZSBuZXcgcm91dGUgc3RhcnRzCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDMwNDYwODkgJiBSb3dOdW1fT0cgPD0gMzA0NjEwOSkgIyAzMDQ2MDk5ICAtLSAgcmVzdWx0cyBmcm9tIGEgcm91dGUgY2hhbmdlLCBhbmQgYSAzaHIgd2FpdCBiZWZvcmUgdGhlIG5ldyByb3V0ZSBzdGFydHMKICAgICAgICAgICApCiAgICApCgoKIyBleGFtcGxlcyBvZiBUcmF2ZWxUaW1lX1NlYyB2YWx1ZXMgdGhhdCBhcmUgdGhlIHNtYWxsZXN0IG9mIHRoZSBsYXJnZS4KVmlldyhmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAoUm93TnVtX09HID49IDMwNDQ2ODkgJiBSb3dOdW1fT0cgPD0gMzA0NDcwOSkgfCAjIDMwNDQ2OTkgIC0tICByZXN1bHRzIGZyb20gYSByb3V0ZSBjaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMzAyMjM1OCAmIFJvd051bV9PRyA8PSAzMDIyMzc4KSB8ICMgMzAyMjM2OCAgLS0gIHJlc3VsdHMgZnJvbSBhIHJvdXRlIGNoYW5nZQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyOTkzMDE2ICYgUm93TnVtX09HIDw9IDI5OTMwMzYpIHwgIyAyOTkzMDI2ICAtLSAgcmVzdWx0cyBmcm9tIGEgcHJldmlvdXMgcm91dGUgY2hhbmdlIChjaGFuZ2Ugb2NjdXJyZWQgaW4gZGVsZXRlZCByb3cpCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDI2ODM3MDMgJiBSb3dOdW1fT0cgPD0gMjY4MzcyMykgIyAyNjgzNzEzICAtLSAgcmVzdWx0cyBmcm9tIGEgcHJldmlvdXMgcm91dGUgY2hhbmdlIChjaGFuZ2Ugb2NjdXJyZWQgaW4gZGVsZXRlZCByb3cpCiAgICAgICAgICAgKQogICAgKQoKYGBgCgoKTGV0J3MgbG9vayBhdCB0aGUgVHJhdmVsVGltZV9TZWMgdmFsdWVzIGFuZCByb3V0ZSBjaGFuZ2VzIChEaXJDaGFuZ2UyKS4KClRoZSA5OXRoIHBlcmNlbnRpbGUgb2YgVHJhdmVsVGltZV9TZWMgZm9yIGJvdGgsIGFsbCB0cmlwcywgYW5kIGp1c3QgdGhvc2UgdHJpcHMgTk9UIGludm9sdmluZyByb3V0ZSBjaGFuZ2VzIChEaXJDaGFuZ2UyID0gIlNhbWUiKSwgaXMgYXBwcm94aW1hdGVseSA1bWluICgzMDAgc2VjKS4KCk5vdGEgQmVuZTogIFRoZSBwZXJjZW50aWxlIGNhbGN1bGF0aW9uIGhlcmUgaXMgZGVmaW5lZCBzbGlnaHRseSBkaWZmZXJlbnQgdGhhbiBpbiBtb3N0IG9mIHRoZSBhYm92ZSBhbmFseXNlcyAod2hpY2ggZ2V0IHRoZSBsb3dlc3QgdmFsdWUgaW4gdGhlIGJpbiBjcmVhdGVkIGJ5IDEwMCBudGlsZXMpLgpgYGB7cn0KCnN1bW1hcnkoc2VsZWN0KE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMKICAgICAgICAgICAgICApCiAgICAgICApCgpzdW1tYXJ5KHNlbGVjdChmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAgICAgICAgICAgRGlyQ2hhbmdlMiA9PSAiU2FtZSIKICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMKICAgICAgICAgICAgICApCiAgICAgICApCgpzdW1tYXJ5KHNlbGVjdChmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAgICAgICAgICAgRGlyQ2hhbmdlMiA9PSAiQ2hhbmdlIgogICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYwogICAgICAgICAgICAgICkKICAgICAgICkKCgpUcmF2VGltZVNlY19RdGlsZXNfZGYgPC0gZGF0YS5mcmFtZShQY3RWYWx1ZSA9IHNlcSgwLCAxMDAsIDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBbGwgPSBzZXEoMSwgMTAxLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2FtZSA9IHNlcSgxLCAxMDEsIDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDaGFuZ2UgPSBzZXEoMSwgMTAxLCAxKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKClRyYXZUaW1lU2VjX1F0aWxlc19kZlsgLCAyXSA8LSBxdWFudGlsZShzZWxlY3QoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBzZXEoMCwgMSwgMC4wMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKVHJhdlRpbWVTZWNfUXRpbGVzX2RmWyAsIDNdIDwtIHF1YW50aWxlKHNlbGVjdChmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEaXJDaGFuZ2UyID09ICJTYW1lIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9icyA9IHNlcSgwLCAxLCAwLjAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpUcmF2VGltZVNlY19RdGlsZXNfZGZbICwgNF0gPC0gcXVhbnRpbGUoc2VsZWN0KGZpbHRlcihOb091dGxpZXJzU3BlZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERpckNoYW5nZTIgPT0gIkNoYW5nZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBzZXEoMCwgMSwgMC4wMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKVmlldyhUcmF2VGltZVNlY19RdGlsZXNfZGYpCgpgYGAKCgpMaW1pdCB0aGUgZGF0YXNldCBub3cgYmFzZWQgb24gVHJhdmVsVGltZV9TZWMuCmBgYHtyfQoKVXBwZXJMaW1pdFRyYXZUaW1lIDwtIGZpbHRlcihOb091dGxpZXJzU3BlZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPD0gNDkxICMgbWluIGF0IHRoZSAxMDB0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKbnJvdyhOb091dGxpZXJzU3BlZWQpIC0gbnJvdyhVcHBlckxpbWl0VHJhdlRpbWUpCgpzdHIoVXBwZXJMaW1pdFRyYXZUaW1lKQoKc3VtbWFyeShVcHBlckxpbWl0VHJhdlRpbWUpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIER3ZWxsX1RpbWUyIChob3cgbG9uZyB0aGUgYnVzIGlzIGF0IGEgc3RvcCkuCgpEaWZmZXJlbmNlcyBiZXR3ZWVuIER3ZWxsX1RpbWUgKGJ5IFdNQVRBKSBhbmQgRHdlbGxfVGltZTIgKGJ5IG1lKSBhcHBlYXIgdG8gYmUgZHVlIHRvIHN3aXRjaGVzIGluIFJvdXRlQWx0LiBXTUFUQSBjYWxjdWxhdGVzIER3ZWxsX1RpbWUgYnkgYW4gdW5rbm93biBwcm9jZXNzLiBUaGUgV01BVEEgY2FsY3VsYXRpb24gaXMgZXF1YWwgdG8gbXkgY2FsY3VsYXRpb24sIGV4Y2VwdCBmb3IgdGhlIHJlY29yZHMgaW1tZWRhaXRlbHkgYmVmb3JlIGFuZCBhZnRlciBhIFJvdXRlQWx0IHN3aXRjaCAoRGlyQ2hhbmdlMikuCmBgYHtyfQoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgRHdlbGxfVGltZSAhPSBEd2VsbF9UaW1lMgogICAgICAgICAgICkKICAgICkKCgojIEV4YW1wbGVzIHdoZXJlIHRoZSBEd2VsbF9UaW1lIGFuZCBEd2VsbF9UaW1lMiBhcmUgZGlmZmVyZW50ClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICggKFJvd051bV9PRyA+PSA2NSAmIFJvd051bV9PRyA8PSA4NSkgfCAjIDc1CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDE2MiAmIFJvd051bV9PRyA8PSAxOTIpIHwgIyAxNzIKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNDMxOTUyICYgUm93TnVtX09HIDw9IDQzMTk3MikgfCAjIDQzMTk2MgogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA0MzQ1OTUgJiBSb3dOdW1fT0cgPD0gNDM0NjE1KSAjIDQzNDYwNSAgLS0gIHRoaXMgcmVjb3JkIGlzIE5PVCBhIHJvdXRlIHN3aXRjaCwgYnV0IGRvZXMgaGFzIGEgU2VxdWVuY2Ugc3dpdGNoIChNZTogc2hvdWxkIHRoZXJlIHJlYWxseSBiZSBhIHJvdXRlIHN3aXRjaCBoZXJlPykKICAgICAgICAgICAgKQogICAgICAgICAgICkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRHdlbGxfVGltZTIgKGhvdyBsb25nIHRoZSBidXMgaXMgYXQgYSBzdG9wKS4KCkZpcnN0LCBjcmVhdGUgc29tZSAicmFuayIgc3RhdHMuClZpZXcoRFQyX1BjdGlsZXMpOiA5NSUgb2YgRHdlbGxfVGltZTJzIGFyZSA8PSAyMyBzZWNvbmRzLi4uYnV0IHNvbWUgd2VpcmQgKGUuZy4sIG5lYXJseSAyIGhvdXIgRHdlbGxfVGltZTJzIGV4aXN0KS4KYGBge3J9CgpEd2VsbFRpbWUyX050aWxlIDwtIGFzLmRhdGEuZnJhbWUoQWxsRGF5c19OZXdPcmRlciREd2VsbF9UaW1lMikgJT4lIAogIG11dGF0ZShQY3RpbGUgPSBudGlsZShBbGxEYXlzX05ld09yZGVyJER3ZWxsX1RpbWUyLCAxMDApLAogICAgICAgICBNaW5SID0gbWluX3JhbmsoQWxsRGF5c19OZXdPcmRlciREd2VsbF9UaW1lMiksCiAgICAgICAgIFBjdFIgPSBwZXJjZW50X3JhbmsoQWxsRGF5c19OZXdPcmRlciREd2VsbF9UaW1lMiksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkgCgpjb2xuYW1lcyhEd2VsbFRpbWUyX050aWxlKVsxXSA8LSAiRHdlbGxfVGltZTIiCnN0cihEd2VsbFRpbWUyX050aWxlKQoKRHdlbGxUaW1lMl9OdGlsZV9Sb3dzIDwtIG5yb3coRHdlbGxUaW1lMl9OdGlsZSkKClZpZXcodGFpbChEd2VsbFRpbWUyX050aWxlLCA1MDApKQoKCkR3ZWxsVGltZTJfUGN0aWxlcyA8LSBncm91cF9ieShEd2VsbFRpbWUyX050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGN0Ul9Sb3VuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5Ed2VsbEF0UGN0aWxlID0gbWluKER3ZWxsX1RpbWUyKSwKICAgIENudHNBdFBjdGlsZSA9IG4oKSwKICAgIFBjdHNBdFBjdGlsZSA9IENudHNBdFBjdGlsZSAvIER3ZWxsVGltZTJfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSkKICAgICAgICApCgpWaWV3KER3ZWxsVGltZTJfUGN0aWxlcykKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRHdlbGxfVGltZTIgKGhvdyBsb25nIHRoZSBidXMgaXMgYXQgYSBzdG9wKS4KCkhpc3RvZ3JhbSBvZiBEd2VsbF9UaW1lMi4KYGBge3J9CgpEd2VsbFRpbWUyX0hpc3REZW4gPC0gZ2dwbG90KEFsbERheXNfTmV3T3JkZXIsIGFlcyh4ID0gRHdlbGxfVGltZTIsIHkgPSAuLmRlbnNpdHkuLikpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3VyID0gImdyZXk2MCIsIHNpemUgPSAwLjIpICsKICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgY29sb3VyID0gInJlZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMSwgMjUpLCB5bGltID0gYygwLCAwLjA1KQogICAgICAgICAgICAgICAgICkgKwogIHhsYWIoIlRpbWUgYSBCdXMgU3RheXMgYXQgYSBTdG9wIChzZWMpIikgKyAKICB5bGFiKCJEZW5zaXR5IikgKyAKICAjICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArIAogIGdndGl0bGUoZXhwcmVzc2lvbihhdG9wKCJWYXJpYXRpb24gaW4gSG93IExvbmcgYSBCdXMgU3RheXMgYXQgYSBTdG9wIgogICAgICAgICAgICAgICAgICAgICAgICAgICMgLGF0b3AoaXRhbGljKCJ4eHh4eCIpLCIiKQogICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgKQoKRHdlbGxUaW1lMl9IaXN0RGVuCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIER3ZWxsX1RpbWUyIChob3cgbG9uZyB0aGUgYnVzIGlzIGF0IGEgc3RvcCkuCgpMb29raW5nIGF0IHNvbWUgd2VpcmRseSBsb25nIER3ZWxsX1RpbWUyIHZhbHVlcy4KYGBge3J9CgpWaWV3KGFycmFuZ2UoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgIGRlc2MoRHdlbGxfVGltZTIpCiAgICAgICAgICAgICkKICAgICkKCgojIGV4YW1wbGVzIG9mIGV4dHJlbWVseSBsYXJnZSBEd2VsbF9UaW1lMnMKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyOTI2NjkgJiBSb3dOdW1fT0cgPD0gMjkyNjg5KSB8ICMgMjkyNjc5CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDUzMTA1NyAmIFJvd051bV9PRyA8PSA1MzEwNzcpIHwgIyA1MzEwNjcKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTM4ODYyNyAmIFJvd051bV9PRyA8PSAxMzg4NjQ3KSB8ICMgMTM4ODYzNwogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNjQ1NzExICYgUm93TnVtX09HIDw9IDE2NDU3MzEpICMgMTY0NTcyMQogICAgICAgICAgICkKICAgICkKCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBEd2VsbF9UaW1lMiA9PSAwCiAgICAgICAgICAgKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEZWx0YV9UaW1lIChob3cgZWFybHkgb3IgbGF0ZSB0aGUgYnVzIGlzKS4KClZpZXcoRFQyX1BjdGlsZXMpOiA5NCUgb2YgRGVsdGFfVGltZSB2YWx1ZXMgYXJlIGJldHdlZW4gLTIzNiBzZWNvbmRzIGFuZCAxLDI1OSBzZWNvbmRzLiBSb3VnaGx5IDY2JSBvZiByZWNvcmRzIGFyZSB3aXRoaW4gNSBtaW4gbGF0ZSBhbmQgNSBtaW4gZWFybHkuLi5idXQgc29tZSB3ZWlyZCAoZS5nLiwgYWxtb3N0IDUwIG1pbnV0ZSBsYXRlIG9yIDQwIG1pbnV0ZSBlYXJseSkgRGVsdGFfVGltZXMgZXhpc3QuCgpOb3RlIHRoYXQgRGVsdGFfVGltZSBpcyB0aGUgZGlmZmVyZW5jZSBmcm9tIHRoZSBzY2hlZHVsZWQgYnVzIGFycml2YWwuIFNvIGlmIHR3byBidXNlcyBhcmUgc2NoZWR1bGVkIHRvIGFycml2ZSBhdCBhIGRlc3RpbmF0aW9uIGF0IDEwOjAwcG0gYW5kIDEwOjIwcG0sIGFuZCBpZiB0aGUgMTA6MjBwbSBidXMgaGFzIGEgRGVsdGFfVGltZSBvZiA1IG1pbnV0ZXMsIHRoZXJlIGFyZSAyNSBtaW51dGVzIGJldHdlZW4gYnVzIGFycml2YWxzIGF0IHRoZSBzdG9wLgoKQWxzbyBub3RlIHRoYXQgYmFzZWQgb24gYSBjb21tZW50IGF0IGh0dHBzOi8vcGxhbml0bWV0cm8uY29tLzIwMTYvMTEvMTYvZGF0YS1kb3dubG9hZC1tZXRyb2J1cy12ZWhpY2xlLWxvY2F0aW9uLWRhdGEvLCB0aGUgRGVsdGFfVGltZSB2YWx1ZXMgZG9uJ3QgYXBwZWFyIHRvIGNvaW5jaWRlIHdpdGggcHVibGlzaGVkIGJ1cyBzY2hlZHVsZXMgKGUuZy4sIHRoZSBYMiBkZXBhcnRpbmcgZXZlcnkgOCBtaW51dGVzIGR1cmluZyBwZWFrIGhvdXJzKS4KYGBge3J9CgpEZWx0VGltZV9OdGlsZSA8LSBhcy5kYXRhLmZyYW1lKEFsbERheXNfTmV3T3JkZXIkRGVsdGFfVGltZSkgJT4lIAogIG11dGF0ZShQY3RpbGUgPSBudGlsZShBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUsIDEwMCksCiAgICAgICAgIE1pblIgPSBtaW5fcmFuayhBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3T3JkZXIkRGVsdGFfVGltZSksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkgCgpjb2xuYW1lcyhEZWx0VGltZV9OdGlsZSlbMV0gPC0gIkRlbHRhX1RpbWUiCnN0cihEZWx0VGltZV9OdGlsZSkKCkRlbHRUaW1lX050aWxlX1Jvd3MgPC0gbnJvdyhEZWx0VGltZV9OdGlsZSkKClZpZXcodGFpbChEZWx0VGltZV9OdGlsZSwgNTAwKSkKCgpEZWx0VGltZV9QY3RpbGVzIDwtIGdyb3VwX2J5KERlbHRUaW1lX050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pbkRlbHRUaW1lQXRQY3RpbGUgPSBtaW4oRGVsdGFfVGltZSksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBEZWx0VGltZV9OdGlsZV9Sb3dzCiAgKSAlPiUgCiAgbXV0YXRlKEN1bVN1bVBBdFAgPSBjdW1zdW0oUGN0c0F0UGN0aWxlKQogICAgICAgICkKClZpZXcoRGVsdFRpbWVfUGN0aWxlcykKRGVsdFRpbWVfUGN0aWxlcwoKIyB+NjYlIG9mIHJvd3MgYXJlIGJldHdlZW4gNSBtaW4gbGF0ZSBhbmQgNSBtaW4gZWFybHkKbnJvdyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgRGVsdGFfVGltZSA+PSAtMzAwICYKICAgICAgICAgICAgICBEZWx0YV9UaW1lIDw9IDMwMAogICAgICAgICAgICkKICAgICkgLyBucm93KEFsbERheXNfTmV3T3JkZXIpCgoKIyBleGFtcGxlcyBvZiB3ZWlyZCBsYXJnZSBEZWx0YV9UaW1lcwpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBEZWx0YV9UaW1lIDwgLTQyMDIgfAogICAgICAgICAgICAgIERlbHRhX1RpbWUgPiAxNzA1CiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoRGVsdGFfVGltZSkKICAgICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIERlbHRhX1RpbWUgKGhvdyBlYXJseSBvciBsYXRlIHRoZSBidXMgaXMpLgoKRGVsdGFfVGltZSBoaXN0b2dyYW0uCmBgYHtyfQoKRGVsdFRpbWVfSGlzdERlbiA8LSBnZ3Bsb3QoQWxsRGF5c19OZXdPcmRlciwgYWVzKHggPSAoRGVsdGFfVGltZSAvIDYwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAuLmRlbnNpdHkuLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAoNS82MCksIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3VyID0gImdyZXk2MCIsIHNpemUgPSAwLjIpICsKICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgY29sb3VyID0gInJlZCIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTUsIDUpKSArCiAgeGxhYigiQnVzIExhdGVuZXNzIChtaW4pIikgKyAKICB5bGFiKCJEZW5zaXR5IikgKyAKICAjICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArIAogIGdndGl0bGUoZXhwcmVzc2lvbihhdG9wKCJWYXJpYXRpb24gaW4gSG93IEVhcmx5L0xhdGUgYSBCdXMgSXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGF0b3AoaXRhbGljKCIocG9zaXRpdmUgdmFsdWVzIGFyZSBsYXRlIGFycml2YWxzKSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgKQoKRGVsdFRpbWVfSGlzdERlbgoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEZWx0YV9UaW1lIChob3cgZWFybHkgb3IgbGF0ZSB0aGUgYnVzIGlzKS4KCkRlbHRhX1RpbWUgYm94cGxvdC4KYGBge3J9CgojIENvdW50X1ZhbHVlcyBpcyBuZWVkZWQgdG8gZGlzcGxheSB0aGUgbWVkaWFucyBvbiB0aGUgYm94IHBsb3RzCkNvdW50X1ZhbHVlcyA8LSBkZHBseShBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgICAgLihFdmVudF9UaW1lX0hyR3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlLAogICAgICAgICAgICAgICAgICAgICAgVmFsdWVfQ291bnRzID0gbWVkaWFuKERlbHRhX1RpbWUgLyA2MCwgbmEucm0gPSBUUlVFKQogICAgICAgICAgICAgICAgICAgICApCgpEZWx0VGltZV9Cb3hQbG90IDwtIGdncGxvdChBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoZmFjdG9yKEV2ZW50X1RpbWVfSHJHcm91cCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWx0YV9UaW1lIC8gNjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gZmFjdG9yKEV2ZW50X1RpbWVfSHJHcm91cCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICkgKyAKICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXI9InJlZCIsIG5vdGNoPVRSVUUpICsgCiAgIyBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTMwMCwgMTIwMCkpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTUsIDIwKSkgKwogIGdlb21fdGV4dChkYXRhID0gQ291bnRfVmFsdWVzLAogICAgICAgICAgICBhZXMoeSA9IFZhbHVlX0NvdW50cywKICAgICAgICAgICAgICAgIGxhYmVsID0gZm9ybWF0KHJvdW5kKFZhbHVlX0NvdW50cywgZGlnaXRzID0gMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuc21hbGwgPSAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNQogICAgICAgICAgICkgKwogIHhsYWIoIkhvdXIgR3JvdXAiKSArIAogIHlsYWIoIkJ1cyBMYXRlbmVzcyAobWludXRlcykiKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1KSkgKyAKICAjdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIsIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKSArIAogIGdndGl0bGUoZXhwcmVzc2lvbihhdG9wKCJIb3cgRWFybHkvTGF0ZSBpcyB0aGUgQnVzIChieSBIb3VyIEdyb3VwKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXRvcChpdGFsaWMoIihwb3NpdGl2ZSB2YWx1ZXMgYXJlIGxhdGUgYXJyaXZhbHMpIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICApCgpEZWx0VGltZV9Cb3hQbG90CgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIERlbHRhX1RpbWUgKGhvdyBlYXJseSBvciBsYXRlIHRoZSBidXMgaXMpLgoKRXhwbG9yaW5nICJleHRyZW1lIiBEZWx0YV9UaW1lcy4gIEZpcnN0IGxldCdzIGdldCBzb21lICJyYW5rIiBzdGF0cy4KYGBge3J9CgpWaWV3KERlbHRUaW1lX1BjdGlsZXMpCkRlbHRUaW1lX1BjdGlsZXMKCgpEZWx0VGltZUFic19OdGlsZSA8LSBhcy5kYXRhLmZyYW1lKGFicyhBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpKSAlPiUgCiAgbXV0YXRlKFBjdGlsZSA9IG50aWxlKGFicyhBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpLCAxMDApLAogICAgICAgICBNaW5SID0gbWluX3JhbmsoYWJzKEFsbERheXNfTmV3T3JkZXIkRGVsdGFfVGltZSkpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKGFicyhBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpKSwKICAgICAgICAgUGN0Ul9Sb3VuZCA9IHJvdW5kKFBjdFIsIDIpCiAgICAgICAgKSAKCmNvbG5hbWVzKERlbHRUaW1lQWJzX050aWxlKVsxXSA8LSAiRGVsdGFfVGltZV9BYnMiCnN0cihEZWx0VGltZUFic19OdGlsZSkKCkRlbHRUaW1lQWJzX050aWxlX1Jvd3MgPC0gbnJvdyhEZWx0VGltZUFic19OdGlsZSkKClZpZXcodGFpbChEZWx0VGltZUFic19OdGlsZSwgNTAwKSkKCgpEZWx0VGltZUFic19QY3RpbGVzIDwtIGdyb3VwX2J5KERlbHRUaW1lQWJzX050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pbkRlbHRUaW1lQXRQY3RpbGUgPSBtaW4oRGVsdGFfVGltZV9BYnMpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gRGVsdFRpbWVfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSkKICAgICAgICApCgpWaWV3KERlbHRUaW1lQWJzX1BjdGlsZXMpCkRlbHRUaW1lQWJzX1BjdGlsZXMKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRGVsdGFfVGltZSAoaG93IGVhcmx5IG9yIGxhdGUgdGhlIGJ1cyBpcykuCgpFeHBsb3JpbmcgImV4dHJlbWUiIERlbHRhX1RpbWVzLiAgVGhlbiBsZXQncyBjYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2Ugb2YgYnVzZXMgdGhhdCBhcmUgMTAgbWludXRlcyAob3IgbW9yZSkgbGF0ZS9lYXJseS4KYGBge3J9CgpIckdyb3VwX0RlbHRhVGltZV9BbGwgPC0gZ3JvdXBfYnkoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfSHJHcm91cAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoRXZlbnRBbGxfQ250ID0gbigpCiAgICAgICAgICAgKQoKc3RyKEhyR3JvdXBfRGVsdGFUaW1lX0FsbCkKVmlldyhIckdyb3VwX0RlbHRhVGltZV9BbGwpCgoKSHJHcm91cF9EZWx0YVRpbWVfQWJvdmUxME1pbiA8LSBmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWJzKERlbHRhX1RpbWUpID49IDYwMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIGdyb3VwX2J5KEV2ZW50X1RpbWVfSHJHcm91cCkgJT4lIAogIHN1bW1hcmlzZShFdmVudEFib3ZlMTBfQ250ID0gbigpCiAgICAgICAgICAgKQoKc3RyKEhyR3JvdXBfRGVsdGFUaW1lX0Fib3ZlMTBNaW4pClZpZXcoSHJHcm91cF9EZWx0YVRpbWVfQWJvdmUxME1pbikKCgpIckdyb3VwX0RlbHRhVGltZUNvbXBhcmUgPC0gaW5uZXJfam9pbihIckdyb3VwX0RlbHRhVGltZV9BYm92ZTEwTWluLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBIckdyb3VwX0RlbHRhVGltZV9BbGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiRXZlbnRfVGltZV9Ickdyb3VwIiA9ICJFdmVudF9UaW1lX0hyR3JvdXAiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShQY3RFdmVudHNBYm92ZTEwID0gRXZlbnRBYm92ZTEwX0NudCAvIEV2ZW50QWxsX0NudCkKClZpZXcoSHJHcm91cF9EZWx0YVRpbWVDb21wYXJlKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEZWx0YV9UaW1lIChob3cgZWFybHkgb3IgbGF0ZSB0aGUgYnVzIGlzKS4KClF1aWNrbHkgcGxvdCB0aGVzZSAiZXh0cmVtZSIgRGVsdGFfVGltZXMuIApgYGB7cn0KCkRlbHRUaW1lX0Fib3ZlMTBfQ29scyA8LSBnZ3Bsb3QoSHJHcm91cF9EZWx0YVRpbWVDb21wYXJlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyhmYWN0b3IoRXZlbnRfVGltZV9Ickdyb3VwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGN0RXZlbnRzQWJvdmUxMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21fY29sKGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3VyID0gImdyZXk2MCIsIHNpemUgPSAwLjIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gZm9ybWF0KHJvdW5kKFBjdEV2ZW50c0Fib3ZlMTAsIGRpZ2l0cyA9IDIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnNtYWxsID0gMgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICBudWRnZV95ID0gKEhyR3JvdXBfRGVsdGFUaW1lQ29tcGFyZSRQY3RFdmVudHNBYm92ZTEwICogLTAuMSkKICAgICAgICAgICApICsKICAjIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygtNSwgNSkpICsKICB4bGFiKCJIb3VyIEdyb3VwIikgKyAKICB5bGFiKCJQZXJjZW50IG9mIEFsbCBCdXMgQXJyaXZhbHMiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUpKSArCiAgZ2d0aXRsZShleHByZXNzaW9uKGF0b3AoIldoZW4gaXMgYSBCdXMgMTArIE1pbnV0ZXMgTGF0ZS9FYXJseSIKICAgICAgICAgICAgICAgICAgICAgICAgICAjICxhdG9wKGl0YWxpYygicG9zaXRpdmUgdmFsdWVzIGFyZSBsYXRlIGFycml2YWxzIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICIiCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgKQoKRGVsdFRpbWVfQWJvdmUxMF9Db2xzCgpgYGAKCgpRdWljayBpbnZlc3RpZ2F0aW9uIG9uIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBEd2VsbF9UaW1lMiAodGhlIHRpbWUgYSBidXMgaXMgYXQgYSBzdG9wKSBhbmQgRGVsdGFfVGltZSAoaG93IGVhcmx5L2xhdGUgdGhlIGJ1cyBpcykuCgpDb3JyZWxhdGlvbi4KYGBge3J9CgpEd2VsbFREZWx0YVRfQ29yciA8LSBhcy5tYXRyaXgoY29yKHggPSBBbGxEYXlzX05ld09yZGVyJER3ZWxsX1RpbWUyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlID0gInBhaXJ3aXNlIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKRHdlbGxURGVsdGFUX0NvcnIKCmBgYAoKClF1aWNrIGludmVzdGlnYXRpb24gb24gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIER3ZWxsX1RpbWUyICh0aGUgdGltZSBhIGJ1cyBpcyBhdCBhIHN0b3ApIGFuZCBEZWx0YV9UaW1lIChob3cgZWFybHkvbGF0ZSB0aGUgYnVzIGlzKS4KCk5leHQsIGxldCdzIGdldCBhIHNhbXBsZSBvZiBkYXRhIGZvciBwbG90dGluZy4gTGV0J3MgZG8gdGhpcyBmb3IgdGhlIGZ1bGwgZGF0YXNldCAoQWxsRGF5c19OZXdPcmRlcikuCmBgYHtyfQoKQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXAgPC0gc2FtcGxlX2ZyYWMoQWxsRGF5c19OZXdPcmRlciwgMC4xKSAlPiUgCiAgc2VsZWN0KERlbHRhX1RpbWUsCiAgICAgICAgIER3ZWxsX1RpbWUyCiAgICAgICAgKSAlPiUgCiAgbXV0YXRlKERhdGFTZXQgPSAiQWxsRGF0YSIpCgpzdHIoQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXApCgpgYGAKCgpRdWljayBpbnZlc3RpZ2F0aW9uIG9uIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBEd2VsbF9UaW1lMiAodGhlIHRpbWUgYSBidXMgaXMgYXQgYSBzdG9wKSBhbmQgRGVsdGFfVGltZSAoaG93IGVhcmx5L2xhdGUgdGhlIGJ1cyBpcykuCgpMZXQncyBhbHNvIGdldCBhIHNhbXBsZSBvZiBkYXRhIGZvciBwbG90dGluZywgYnV0IHdpdGggYSBkYXRzZXQgdGhhdCByZW1vdmVzIG91dGxpZXJzLgpgYGB7cn0KClZpZXcoRGVsdFRpbWVfUGN0aWxlcykKVmlldyhEd2VsbFRpbWUyX1BjdGlsZXMpCgpBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wIDwtIGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZXR3ZWVuKERlbHRhX1RpbWUsIC00MDIsIDE3MDUpICYgIyByZW1vdmVzIGFib3V0IDIlIG9mIERlbHRhX1RpbWUgdmFsdWVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV0d2VlbihEd2VsbF9UaW1lMiwgMSwgNjMpICAjIHJlbW92ZXMgYWJvdXQgMiUgb2YgRHdlbGxfVGltZTIgdmFsdWVzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc2FtcGxlX2ZyYWMoMC4xKSAlPiUgCiAgc2VsZWN0KERlbHRhX1RpbWUsCiAgICAgICAgIER3ZWxsX1RpbWUyCiAgICAgICAgKSAlPiUgCiAgbXV0YXRlKERhdGFTZXQgPSAiT3V0bGllcnNSZW1vdmVkIikKCnN0cihBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wKQoKYGBgCgoKUXVpY2sgaW52ZXN0aWdhdGlvbiBvbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gRHdlbGxfVGltZTIgKHRoZSB0aW1lIGEgYnVzIGlzIGF0IGEgc3RvcCkgYW5kIERlbHRhX1RpbWUgKGhvdyBlYXJseS9sYXRlIHRoZSBidXMgaXMpLgoKUGxvdHRpbmcgdGhlIGRhdGEgZnJvbSB0aGUgZGF0YXNldCB0aGF0IGRvZXMgbm90IHJlbW92ZSBvdXRsaWVycy4KYGBge3J9CgpEd2VsbFREZWx0YVRfU2NhdHRlciA8LSBnZ3Bsb3QoQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoRHdlbGxfVGltZTIsIERlbHRhX1RpbWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAxLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX3NoYXBlKHNvbGlkID0gRkFMU0UpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvdXIgPSAicmVkIikgKwogICMgeGxhYigiVGltZSBhdCBTdG9wIChzZWMpIikgKyAKICAjIHlsYWIoIkxhdGVuZXNzIChzZWMpIikgKwogIGFubm90YXRlKGxhYmVsID0gbG1fZXFuKGRmID0gQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wJERlbHRhX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wJER3ZWxsX1RpbWUyCiAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgIHggPSAyMjAwLAogICAgICAgICAgIHkgPSA2MDAsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAicmVkIiwKICAgICAgICAgICBwYXJzZSA9IFRSVUUKICAgICAgICAgICkgKwogIGxhYnModGl0bGUgPSAiTGF0ZW5lc3MgdnMgVGltZSBhdCBTdG9wIiwKICAgICAgIHN1YnRpdGxlID0gIihubyBvdXRsaWVycyByZW1vdmVkKSIsCiAgICAgICB4ID0gIlRpbWUgYXQgU3RvcCAoc2VjKSIsCiAgICAgICB5ID0gIkxhdGVuZXNzIChzZWMpIgogICAgICApCiAgIyBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiTGF0ZW5lc3MgdnMgVGltZSBhdCBTdG9wIgogICMgICAgICAgICAgICAgICAgICAgICAgICAgLGF0b3AoaXRhbGljKCIobm8gb3V0bGllcnMgcmVtb3ZlZCkiKSwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAjICAgICAgICAgICAgICAgICAgICAgICAgKQogICMgICAgICAgICAgICAgICAgICAgKQogICMgICAgICAgICkKIyArCiMgICBnZW9tX2ppdHRlcigpCgpEd2VsbFREZWx0YVRfU2NhdHRlcgoKYGBgCgoKUXVpY2sgaW52ZXN0aWdhdGlvbiBvbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gRHdlbGxfVGltZTIgKHRoZSB0aW1lIGEgYnVzIGlzIGF0IGEgc3RvcCkgYW5kIERlbHRhX1RpbWUgKGhvdyBlYXJseS9sYXRlIHRoZSBidXMgaXMpLgoKUGxvdHRpbmcgdGhlIGRhdGEgZnJvbSB0aGUgZGF0YXNldCB0aGF0IGRvZXMgcmVtb3ZlIG91dGxpZXJzLgpgYGB7cn0KCkR3ZWxsVERlbHRhVF9TY2F0dGVyX05vRXh0cmVtZXMgPC0gZ2dwbG90KEFsbERheXNfTmV3T3JkZXJfTm9FeHRyZW1lc18xMFBjdFNhbXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyhEd2VsbF9UaW1lMiwgRGVsdGFfVGltZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV9zaGFwZShzb2xpZCA9IEZBTFNFKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3VyID0gImJsdWUiKSArCiAgIyB4bGFiKCJUaW1lIGF0IFN0b3AgKHNlYykiKSArIAogICMgeWxhYigiTGF0ZW5lc3MgKHNlYykiKSArCiAgYW5ub3RhdGUobGFiZWwgPSBsbV9lcW4oZGYgPSBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wJERlbHRhX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IEFsbERheXNfTmV3T3JkZXJfTm9FeHRyZW1lc18xMFBjdFNhbXAkRHdlbGxfVGltZTIKICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgeCA9IDUwLAogICAgICAgICAgIHkgPSAtNDc1LAogICAgICAgICAgIGdlb20gPSAidGV4dCIsCiAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgY29sb3VyID0gImJsdWUiLAogICAgICAgICAgIHBhcnNlID0gVFJVRQogICAgICAgICAgKSArCiAgbGFicyh0aXRsZSA9ICJMYXRlbmVzcyB2cyBUaW1lIGF0IFN0b3AiLAogICAgICAgc3VidGl0bGUgPSAiKDIlIG9mIG91dGxpZXJzIHJlbW92ZWQpIiwKICAgICAgIHggPSAiVGltZSBhdCBTdG9wIChzZWMpIiwKICAgICAgIHkgPSAiTGF0ZW5lc3MgKHNlYykiCiAgICAgICkKICAjIGdndGl0bGUoZXhwcmVzc2lvbihhdG9wKCJMYXRlbmVzcyB2cyBUaW1lIGF0IFN0b3AiCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAsYXRvcChpdGFsaWMoIigyJSBvZiBvdXRsaWVycyByZW1vdmVkKSIpLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiIKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICMgICAgICAgICAgICAgICAgICAgICAgICApCiAgIyAgICAgICAgICAgICAgICAgICApCiAgIyAgICAgICAgKQojICsKIyAgIGdlb21faml0dGVyKCkKCkR3ZWxsVERlbHRhVF9TY2F0dGVyX05vRXh0cmVtZXMKCmBgYAoKClF1aWNrIGludmVzdGlnYXRpb24gb24gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIER3ZWxsX1RpbWUyICh0aGUgdGltZSBhIGJ1cyBpcyBhdCBhIHN0b3ApIGFuZCBEZWx0YV9UaW1lIChob3cgZWFybHkvbGF0ZSB0aGUgYnVzIGlzKS4KClBsb3R0aW5nIHRoZSBkYXRhIGZyb20gYm90aCBkYXRhc2V0cyB0b2dldGhlci4KYGBge3J9CgpDb21iaW5lZERhdGEgPC0gcmJpbmQoQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXAsCiAgICAgICAgICAgICAgICAgICAgICBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wCiAgICAgICAgICAgICAgICAgICAgICkKCkNvbWJpbmVkRGF0YSREYXRhU2V0IDwtIGZhY3RvcihDb21iaW5lZERhdGEkRGF0YVNldCkKCnN0cihDb21iaW5lZERhdGEpCgoKRHdlbGxURGVsdGFUX1NjYXR0ZXJfQ29tYmluZWQgPC0gZ2dwbG90KENvbWJpbmVkRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gRHdlbGxfVGltZTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IERlbHRhX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gRGF0YVNldAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV9zaGFwZShzb2xpZCA9IEZBTFNFKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDUwMCksIHlsaW0gPSBjKC0xMDAwLCAyMDAwKQogICAgICAgICAgICAgICAgICkgKwogIGdlb21fc21vb3RoKGRhdGEgPSBmaWx0ZXIoQ29tYmluZWREYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRGF0YVNldCA9PSAiQWxsRGF0YSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICBtZXRob2QgPSAibG0iLAogICAgICAgICAgICAgIGNvbG91ciA9ICJyZWQiCiAgICAgICAgICAgICApICsKICBnZW9tX3Ntb290aChkYXRhID0gZmlsdGVyKENvbWJpbmVkRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIERhdGFTZXQgPT0gIk91dGxpZXJzUmVtb3ZlZCIKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICBtZXRob2QgPSAibG0iLAogICAgICAgICAgICAgIGNvbG91ciA9ICJibHVlIgogICAgICAgICAgICAgKSArCiAgIyBmYWNldF93cmFwKCB+IERhdGFTZXQsIG5jb2wgPSAyKSArCiAgYW5ub3RhdGUobGFiZWwgPSBsbV9lcW4oZGYgPSBBbGxEYXlzX05ld09yZGVyXzEwUGN0U2FtcCwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXAkRGVsdGFfVGltZSwKICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXAkRHdlbGxfVGltZTIKICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgeCA9IDMwMCwKICAgICAgICAgICB5ID0gLTYwMCwKICAgICAgICAgICBnZW9tID0gInRleHQiLAogICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgIGNvbG91ciA9ICJyZWQiLAogICAgICAgICAgIHBhcnNlID0gVFJVRQogICAgICAgICAgKSArCiAgYW5ub3RhdGUobGFiZWwgPSBsbV9lcW4oZGYgPSBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wJERlbHRhX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IEFsbERheXNfTmV3T3JkZXJfTm9FeHRyZW1lc18xMFBjdFNhbXAkRHdlbGxfVGltZTIKICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgeCA9IDMwMCwKICAgICAgICAgICB5ID0gLTgwMCwKICAgICAgICAgICBnZW9tID0gInRleHQiLAogICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgIGNvbG91ciA9ICJibHVlIiwKICAgICAgICAgICBwYXJzZSA9IFRSVUUKICAgICAgICAgICkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgbGFicyh0aXRsZSA9ICJMYXRlbmVzcyB2cyBUaW1lIGF0IFN0b3AiLAogICAgICAgeCA9ICJUaW1lIGF0IFN0b3AgKHNlYykiLAogICAgICAgeSA9ICJMYXRlbmVzcyAoc2VjKSIKICAgICAgKQogICMgZ2d0aXRsZShleHByZXNzaW9uKGF0b3AoIkxhdGVuZXNzIHZzIFRpbWUgYXQgU3RvcCIKICAgICAgICAgICAgICAgICAgICAgICAgICAjICxhdG9wKGl0YWxpYygiMiUgb2Ygb3V0bGllcnMgcmVtb3ZlZCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgIiIKICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgKQogICAgICAgICAjICAgICAgICAgICAgICAgICApCiAgICAgICAgICMgICAgICAgICAgICApCiAgICAgICAgICMgKQojICsKIyAgIGdlb21faml0dGVyKCkKCkR3ZWxsVERlbHRhVF9TY2F0dGVyX0NvbWJpbmVkCgpgYGAKCgoKCgoKCgoKCgpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ21kK09wdGlvbitJKi4KCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ21kK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuCg==